Bug 1567241 - Update to euclid 0.20. r=kvark, emilio.
authorNicolas Silva <nsilva@mozilla.com>
Thu, 18 Jul 2019 22:54:16 +0200
changeset 483440 4c9962d08d72dbc1503d7446a46dd4782e2a259b
parent 483439 f95b558d97fb03b3a5cb2c9b8b26f5015d7bd77a
child 483441 927c1651317bd5e7c69635a48924643e81bc3079
push id113723
push usernsilva@mozilla.com
push dateFri, 19 Jul 2019 07:57:39 +0000
treeherdermozilla-inbound@4c9962d08d72 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark, emilio
bugs1567241
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1567241 - Update to euclid 0.20. r=kvark, emilio. Differential Revision: https://phabricator.services.mozilla.com/D38530
Cargo.lock
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/Moz2DImageRenderer.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/wr/Cargo.lock
gfx/wr/direct-composition/Cargo.toml
gfx/wr/direct-composition/src/main_windows.rs
gfx/wr/examples/Cargo.toml
gfx/wr/examples/common/boilerplate.rs
gfx/wr/examples/document.rs
gfx/wr/examples/frame_output.rs
gfx/wr/examples/multiwindow.rs
gfx/wr/peek-poke/Cargo.toml
gfx/wr/peek-poke/src/euclid.rs
gfx/wr/webrender/Cargo.toml
gfx/wr/webrender/src/batch.rs
gfx/wr/webrender/src/border.rs
gfx/wr/webrender/src/box_shadow.rs
gfx/wr/webrender/src/clip.rs
gfx/wr/webrender/src/clip_scroll_tree.rs
gfx/wr/webrender/src/debug_render.rs
gfx/wr/webrender/src/device/gl.rs
gfx/wr/webrender/src/display_list_flattener.rs
gfx/wr/webrender/src/ellipse.rs
gfx/wr/webrender/src/gpu_cache.rs
gfx/wr/webrender/src/hit_test.rs
gfx/wr/webrender/src/picture.rs
gfx/wr/webrender/src/platform/macos/font.rs
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/prim_store/text_run.rs
gfx/wr/webrender/src/profiler.rs
gfx/wr/webrender/src/render_task.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/webrender/src/resource_cache.rs
gfx/wr/webrender/src/shade.rs
gfx/wr/webrender/src/spatial_node.rs
gfx/wr/webrender/src/util.rs
gfx/wr/webrender_api/Cargo.toml
gfx/wr/webrender_api/src/display_item.rs
gfx/wr/webrender_api/src/display_list.rs
gfx/wr/webrender_api/src/image.rs
gfx/wr/webrender_api/src/units.rs
gfx/wr/wr_malloc_size_of/Cargo.toml
gfx/wr/wr_malloc_size_of/lib.rs
gfx/wr/wrench/Cargo.toml
gfx/wr/wrench/src/yaml_frame_writer.rs
gfx/wr/wrench/src/yaml_helper.rs
layout/painting/nsCSSRenderingBorders.cpp
servo/components/malloc_size_of/Cargo.toml
servo/components/malloc_size_of/lib.rs
servo/components/style/Cargo.toml
servo/components/style/context.rs
servo/components/style/gecko/media_features.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/logical_geometry.rs
servo/components/style/servo/media_queries.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/computed/transform.rs
servo/components/style/values/distance.rs
servo/components/style/values/generics/transform.rs
servo/components/style/values/specified/length.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/viewport.rs
servo/tests/unit/style/Cargo.toml
servo/tests/unit/style/media_queries.rs
servo/tests/unit/style/stylist.rs
servo/tests/unit/style/viewport.rs
third_party/rust/euclid/.cargo-checksum.json
third_party/rust/euclid/Cargo.toml
third_party/rust/euclid/src/box2d.rs
third_party/rust/euclid/src/box3d.rs
third_party/rust/euclid/src/homogen.rs
third_party/rust/euclid/src/length.rs
third_party/rust/euclid/src/lib.rs
third_party/rust/euclid/src/nonempty.rs
third_party/rust/euclid/src/point.rs
third_party/rust/euclid/src/rect.rs
third_party/rust/euclid/src/rigid.rs
third_party/rust/euclid/src/rotation.rs
third_party/rust/euclid/src/scale.rs
third_party/rust/euclid/src/side_offsets.rs
third_party/rust/euclid/src/size.rs
third_party/rust/euclid/src/transform2d.rs
third_party/rust/euclid/src/transform3d.rs
third_party/rust/euclid/src/translation.rs
third_party/rust/euclid/src/vector.rs
third_party/rust/euclid_macros/.cargo-checksum.json
third_party/rust/euclid_macros/Cargo.toml
third_party/rust/euclid_macros/LICENSE-APACHE
third_party/rust/euclid_macros/LICENSE-MIT
third_party/rust/euclid_macros/euclid_matrix.rs
third_party/rust/euclid_macros/lib.rs
third_party/rust/plane-split/.cargo-checksum.json
third_party/rust/plane-split/Cargo.toml
third_party/rust/plane-split/src/bsp.rs
third_party/rust/plane-split/src/clip.rs
third_party/rust/plane-split/src/lib.rs
third_party/rust/plane-split/src/polygon.rs
third_party/rust/plane-split/tests/clip.rs
third_party/rust/plane-split/tests/main.rs
third_party/rust/plane-split/tests/split.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1058,35 +1058,24 @@ dependencies = [
 
 [[package]]
 name = "error-chain"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "euclid"
-version = "0.19.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+version = "0.20.0"
+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)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "euclid_macros"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "failure"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1744,17 +1733,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
  "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2224,17 +2213,17 @@ dependencies = [
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "peek-poke"
 version = "0.2.0"
 dependencies = [
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke-derive 0.2.0",
 ]
 
 [[package]]
 name = "peek-poke-derive"
 version = "0.2.0"
 dependencies = [
  "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2296,21 +2285,21 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "plain"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "plane-split"
-version = "0.13.8"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "plist"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2974,17 +2963,17 @@ dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.49.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3035,17 +3024,17 @@ dependencies = [
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
  "to_shmem 0.0.1",
  "to_shmem_derive 0.0.1",
 ]
@@ -3646,27 +3635,27 @@ dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "svg_fmt 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3682,17 +3671,17 @@ name = "webrender_api"
 version = "0.60.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke 0.2.0",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "wr_malloc_size_of 0.0.1",
 ]
@@ -3701,17 +3690,17 @@ dependencies = [
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3798,17 +3787,17 @@ dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
 name = "wr_malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "ws"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3998,18 +3987,17 @@ dependencies = [
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
 "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
-"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
-"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
+"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
 "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
 "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 "checksum filetime_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c37abd4a58e0cb794bcae4a7dc4f02fff376949d8d1066d4c729e97bfb38ec"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
@@ -4103,17 +4091,17 @@ dependencies = [
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
-"checksum plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"
+"checksum plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91821c7436aefc1b912552d494232efcaf9810c0189918749532be1e9dbace59"
 "checksum plist 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95bef0807b4fe77618f8d24f0c4ec37a4ad1dad9348c3b27d8b624c824d8cf48"
 "checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -6,17 +6,17 @@ license = "MPL-2.0"
 
 [features]
 webrender_debugger = ["webrender/debugger"]
 
 [dependencies]
 rayon = "1"
 num_cpus = "1.7.0"
 thread_profiler = "0.1.1"
-euclid = { version = "0.19.4", features = ["serde"] }
+euclid = { version = "0.20.0", features = ["serde"] }
 app_units = "0.7"
 gleam = "0.6.14"
 log = "0.4"
 nsstring = { path = "../../xpcom/rust/nsstring" }
 bincode = "1.0"
 uuid = { version = "0.6", features = ["v4"] }
 fxhash = "0.2.1"
 
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -383,17 +383,17 @@ static bool Moz2DRenderCallback(const Ra
     origin +=
         gfx::IntPoint(aTileOffset->x * *aTileSize, aTileOffset->y * *aTileSize);
   }
   dt = gfx::Factory::CreateOffsetDrawTarget(dt, origin);
 
   auto bounds = gfx::IntRect(origin, aSize);
 
   if (aDirtyRect) {
-    Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y,
+    gfx::Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y,
                aDirtyRect->size.width, aDirtyRect->size.height);
     dt->PushClipRect(dirty);
     bounds = bounds.Intersect(
         IntRect(aDirtyRect->origin.x, aDirtyRect->origin.y,
                 aDirtyRect->size.width, aDirtyRect->size.height));
   }
 
   bool ret = true;
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -1133,33 +1133,33 @@ void DisplayListBuilder::PushBorderImage
                           aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
                           &aParams);
 }
 
 void DisplayListBuilder::PushBorderGradient(
     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
     bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths,
     const int32_t aWidth, const int32_t aHeight, bool aFill,
-    const wr::SideOffsets2D<int32_t>& aSlice,
+    const wr::DeviceIntSideOffsets& aSlice,
     const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint,
     const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
-    const wr::SideOffsets2D<float>& aOutset) {
+    const wr::LayoutSideOffsets& aOutset) {
   wr_dp_push_border_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
                              aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
                              aWidths, aWidth, aHeight, aFill, aSlice,
                              aStartPoint, aEndPoint, aStops.Elements(),
                              aStops.Length(), aExtendMode, aOutset);
 }
 
 void DisplayListBuilder::PushBorderRadialGradient(
     const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
     bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
     const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
     const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
-    const wr::SideOffsets2D<float>& aOutset) {
+    const wr::LayoutSideOffsets& aOutset) {
   wr_dp_push_border_radial_gradient(
       mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
       &mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aRadius,
       aStops.Elements(), aStops.Length(), aExtendMode, aOutset);
 }
 
 void DisplayListBuilder::PushText(const wr::LayoutRect& aBounds,
                                   const wr::LayoutRect& aClip,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -506,29 +506,29 @@ class DisplayListBuilder final {
   void PushBorderImage(const wr::LayoutRect& aBounds,
                        const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
                        const wr::WrBorderImage& aParams);
 
   void PushBorderGradient(const wr::LayoutRect& aBounds,
                           const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
                           const wr::LayoutSideOffsets& aWidths,
                           const int32_t aWidth, const int32_t aHeight,
-                          bool aFill, const wr::SideOffsets2D<int32_t>& aSlice,
+                          bool aFill, const wr::DeviceIntSideOffsets& aSlice,
                           const wr::LayoutPoint& aStartPoint,
                           const wr::LayoutPoint& aEndPoint,
                           const nsTArray<wr::GradientStop>& aStops,
                           wr::ExtendMode aExtendMode,
-                          const wr::SideOffsets2D<float>& aOutset);
+                          const wr::LayoutSideOffsets& aOutset);
 
   void PushBorderRadialGradient(
       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
       bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
       const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
       const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
-      const wr::SideOffsets2D<float>& aOutset);
+      const wr::LayoutSideOffsets& aOutset);
 
   void PushText(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
                 bool aIsBackfaceVisible, const wr::ColorF& aColor,
                 wr::FontInstanceKey aFontKey,
                 Range<const wr::GlyphInstance> aGlyphBuffer,
                 const wr::GlyphOptions* aGlyphOptions = nullptr);
 
   void PushLine(const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -622,33 +622,33 @@ static inline wr::LayoutSideOffsets ToBo
   wr::LayoutSideOffsets bw;
   bw.top = top;
   bw.right = right;
   bw.bottom = bottom;
   bw.left = left;
   return bw;
 }
 
-static inline wr::SideOffsets2D<int32_t> ToSideOffsets2D_i32(int32_t top,
-                                                             int32_t right,
-                                                             int32_t bottom,
-                                                             int32_t left) {
-  SideOffsets2D<int32_t> offset;
+static inline wr::DeviceIntSideOffsets ToDeviceIntSideOffsets(int32_t top,
+                                                                int32_t right,
+                                                                int32_t bottom,
+                                                                int32_t left) {
+  wr::DeviceIntSideOffsets offset;
   offset.top = top;
   offset.right = right;
   offset.bottom = bottom;
   offset.left = left;
   return offset;
 }
 
-static inline wr::SideOffsets2D<float> ToSideOffsets2D_f32(float top,
-                                                           float right,
-                                                           float bottom,
-                                                           float left) {
-  SideOffsets2D<float> offset;
+static inline wr::LayoutSideOffsets ToLayoutSideOffsets(float top,
+                                                        float right,
+                                                        float bottom,
+                                                        float left) {
+  wr::LayoutSideOffsets offset;
   offset.top = top;
   offset.right = right;
   offset.bottom = bottom;
   offset.left = left;
   return offset;
 }
 
 static inline wr::RepeatMode ToRepeatMode(
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2775,18 +2775,18 @@ pub extern "C" fn wr_dp_push_border(stat
 
 #[repr(C)]
 pub struct WrBorderImage {
     widths: LayoutSideOffsets,
     image: WrImageKey,
     width: i32,
     height: i32,
     fill: bool,
-    slice: SideOffsets2D<i32>,
-    outset: SideOffsets2D<f32>,
+    slice: DeviceIntSideOffsets,
+    outset: LayoutSideOffsets,
     repeat_horizontal: RepeatMode,
     repeat_vertical: RepeatMode,
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_border_image(state: &mut WrState,
                                           rect: LayoutRect,
                                           clip: LayoutRect,
@@ -2827,23 +2827,23 @@ pub extern "C" fn wr_dp_push_border_grad
                                              rect: LayoutRect,
                                              clip: LayoutRect,
                                              is_backface_visible: bool,
                                              parent: &WrSpaceAndClipChain,
                                              widths: LayoutSideOffsets,
                                              width: i32,
                                              height: i32,
                                              fill: bool,
-                                             slice: SideOffsets2D<i32>,
+                                             slice: DeviceIntSideOffsets,
                                              start_point: LayoutPoint,
                                              end_point: LayoutPoint,
                                              stops: *const GradientStop,
                                              stops_count: usize,
                                              extend_mode: ExtendMode,
-                                             outset: SideOffsets2D<f32>) {
+                                             outset: LayoutSideOffsets) {
     debug_assert!(unsafe { is_in_main_thread() });
 
     let stops_slice = unsafe { make_slice(stops, stops_count) };
     let stops_vector = stops_slice.to_owned();
 
     let gradient = state.frame_builder.dl_builder.create_gradient(
         start_point.into(),
         end_point.into(),
@@ -2888,17 +2888,17 @@ pub extern "C" fn wr_dp_push_border_radi
                                                     parent: &WrSpaceAndClipChain,
                                                     widths: LayoutSideOffsets,
                                                     fill: bool,
                                                     center: LayoutPoint,
                                                     radius: LayoutSize,
                                                     stops: *const GradientStop,
                                                     stops_count: usize,
                                                     extend_mode: ExtendMode,
-                                                    outset: SideOffsets2D<f32>) {
+                                                    outset: LayoutSideOffsets) {
     debug_assert!(unsafe { is_in_main_thread() });
 
     let stops_slice = unsafe { make_slice(stops, stops_count) };
     let stops_vector = stops_slice.to_owned();
 
     let slice = SideOffsets2D::new(
         widths.top as i32,
         widths.right as i32,
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -418,17 +418,17 @@ source = "registry+https://github.com/ru
 dependencies = [
  "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "direct-composition"
 version = "0.1.0"
 dependencies = [
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender 0.60.0",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "winit 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -475,35 +475,24 @@ dependencies = [
  "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "euclid"
-version = "0.19.9"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "euclid_macros"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "expat-sys"
 version = "2.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1135,17 +1124,17 @@ dependencies = [
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "peek-poke"
 version = "0.2.0"
 dependencies = [
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke-derive 0.2.0",
 ]
 
 [[package]]
 name = "peek-poke-derive"
 version = "0.2.0"
 dependencies = [
  "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1162,21 +1151,21 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "pkg-config"
 version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "plane-split"
-version = "0.13.8"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "png"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1878,28 +1867,28 @@ dependencies = [
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1913,17 +1902,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "webrender-examples"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender 0.60.0",
  "winit 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1931,17 +1920,17 @@ name = "webrender_api"
 version = "0.60.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "peek-poke 0.2.0",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "wr_malloc_size_of 0.0.1",
@@ -2023,34 +2012,34 @@ dependencies = [
  "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wr_malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "wrench"
 version = "0.3.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "osmesa-src 0.1.1 (git+https://github.com/servo/osmesa-src)",
@@ -2184,18 +2173,17 @@ dependencies = [
 "checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"
 "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
 "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
 "checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
-"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
-"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
+"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
 "checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
 "checksum font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd330f40acb3016432cbfa4c54b3d6e6e893a538df79d8df8fd8c26e21c36aaa"
 "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
@@ -2263,17 +2251,17 @@ dependencies = [
 "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69376b761943787ebd5cc85a5bc95958651a22609c5c1c2b65de21786baec72b"
 "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
 "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
 "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
 "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
 "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
-"checksum plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"
+"checksum plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91821c7436aefc1b912552d494232efcaf9810c0189918749532be1e9dbace59"
 "checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
 "checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
 "checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
 "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
 "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
--- a/gfx/wr/direct-composition/Cargo.toml
+++ b/gfx/wr/direct-composition/Cargo.toml
@@ -1,14 +1,14 @@
 [package]
 name = "direct-composition"
 version = "0.1.0"
 authors = ["Simon Sapin <simon.sapin@exyr.org>"]
 license = "MPL-2.0"
 edition = "2018"
 
 [target.'cfg(windows)'.dependencies]
-euclid = "0.19"
+euclid = "0.20"
 gleam = "0.6.2"
 mozangle = {version = "0.1", features = ["egl"]}
 webrender = {path = "../webrender"}
 winapi = {version = "0.3", features = ["winerror", "d3d11", "dcomp"]}
 winit = "0.19"
--- a/gfx/wr/direct-composition/src/main_windows.rs
+++ b/gfx/wr/direct-composition/src/main_windows.rs
@@ -128,20 +128,20 @@ impl Rectangle {
             color: api::ColorF { r, g, b, a },
         }
     }
 
     fn render(&mut self, device_pixel_ratio: f32, rx: &mpsc::Receiver<()>) {
         self.visual.make_current();
 
         let pipeline_id = api::PipelineId(0, 0);
-        let layout_size = self.size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
+        let layout_size = self.size.to_f32() / euclid::Scale::new(device_pixel_ratio);
         let mut builder = api::DisplayListBuilder::new(pipeline_id, layout_size);
 
-        let rect = euclid::TypedRect::new(euclid::TypedPoint2D::zero(), layout_size);
+        let rect = euclid::Rect::new(euclid::Point2D::zero(), layout_size);
 
         let region = api::ComplexClipRegion::new(
             rect,
             api::BorderRadius::uniform(20.),
             api::ClipMode::Clip
         );
         let clip_id = builder.define_clip(
             &api::SpaceAndClipInfo::root_scroll(pipeline_id),
--- a/gfx/wr/examples/Cargo.toml
+++ b/gfx/wr/examples/Cargo.toml
@@ -55,14 +55,14 @@ name = "yuv"
 path = "yuv.rs"
 
 [features]
 debug = ["webrender/capture", "webrender/debugger", "webrender/profiler"]
 
 [dependencies]
 app_units = "0.7"
 env_logger = "0.5"
-euclid = "0.19"
+euclid = "0.20"
 gleam = "0.6.2"
 glutin = "0.21"
 rayon = "1"
 webrender = { path = "../webrender" }
 winit = "0.19"
--- a/gfx/wr/examples/common/boilerplate.rs
+++ b/gfx/wr/examples/common/boilerplate.rs
@@ -187,17 +187,17 @@ pub fn main_wrapper<E: Example>(
     }
 
     if let Some(external_image_handler) = external {
         renderer.set_external_image_handler(external_image_handler);
     }
 
     let epoch = Epoch(0);
     let pipeline_id = PipelineId(0, 0);
-    let layout_size = device_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
+    let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
     let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
     let mut txn = Transaction::new();
 
     example.render(
         &api,
         &mut builder,
         &mut txn,
         device_size,
--- a/gfx/wr/examples/document.rs
+++ b/gfx/wr/examples/document.rs
@@ -7,17 +7,17 @@ extern crate gleam;
 extern crate glutin;
 extern crate webrender;
 extern crate winit;
 
 #[path = "common/boilerplate.rs"]
 mod boilerplate;
 
 use crate::boilerplate::Example;
-use euclid::TypedScale;
+use euclid::Scale;
 use webrender::api::*;
 use webrender::api::units::*;
 
 // This example creates multiple documents overlapping each other with
 // specified layer indices.
 
 struct Document {
     id: DocumentId,
@@ -73,17 +73,17 @@ impl App {
             txn.set_root_pipeline(pipeline_id);
             api.send_transaction(document_id, txn);
 
             self.documents.push(Document {
                 id: document_id,
                 pipeline_id,
                 content_rect: LayoutRect::new(
                     LayoutPoint::origin(),
-                    bounds.size.to_f32() / TypedScale::new(device_pixel_ratio),
+                    bounds.size.to_f32() / Scale::new(device_pixel_ratio),
                 ),
                 color,
             });
         }
     }
 }
 
 impl Example for App {
--- a/gfx/wr/examples/frame_output.rs
+++ b/gfx/wr/examples/frame_output.rs
@@ -7,17 +7,17 @@ extern crate gleam;
 extern crate glutin;
 extern crate webrender;
 extern crate winit;
 
 #[path = "common/boilerplate.rs"]
 mod boilerplate;
 
 use crate::boilerplate::{Example, HandyDandyRectBuilder};
-use euclid::TypedScale;
+use euclid::Scale;
 use gleam::gl;
 use webrender::api::*;
 use webrender::api::units::*;
 
 
 // This example demonstrates using the frame output feature to copy
 // the output of a WR framebuffer to a custom texture.
 
@@ -87,17 +87,17 @@ impl App {
             device_pixel_ratio,
         );
 
         let document = Document {
             id: document_id,
             pipeline_id,
             content_rect: LayoutRect::new(
                 LayoutPoint::zero(),
-                device_size.to_f32() / TypedScale::new(device_pixel_ratio),
+                device_size.to_f32() / Scale::new(device_pixel_ratio),
             ),
             color,
         };
 
         let mut txn = Transaction::new();
 
         txn.add_image(
             self.external_image_key.unwrap(),
--- a/gfx/wr/examples/multiwindow.rs
+++ b/gfx/wr/examples/multiwindow.rs
@@ -176,17 +176,17 @@ impl Window {
         let device_size = {
             let size = context
                 .window()
                 .get_inner_size()
                 .unwrap()
                 .to_physical(device_pixel_ratio as f64);
             DeviceIntSize::new(size.width as i32, size.height as i32)
         };
-        let layout_size = device_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
+        let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
         let mut txn = Transaction::new();
         let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
         let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
 
         let bounds = LayoutRect::new(LayoutPoint::zero(), builder.content_size());
         builder.push_simple_stacking_context(
             bounds.origin,
             space_and_clip.spatial_id,
--- a/gfx/wr/peek-poke/Cargo.toml
+++ b/gfx/wr/peek-poke/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "peek-poke"
 version = "0.2.0"
 authors = ["Dan Glastonbury <dan.glastonbury@gmail.com>"]
 license = "MIT/Apache-2.0"
 edition = "2018"
 
 [dependencies]
-euclid = { version = "0.19", optional = true }
+euclid = { version = "0.20.0", optional = true }
 peek-poke-derive = { version = "0.2", path = "./peek-poke-derive", optional = true }
 
 [features]
 default = ["derive"]
 derive = ["peek-poke-derive"]
 extras = ["derive", "euclid"]
--- a/gfx/wr/peek-poke/src/euclid.rs
+++ b/gfx/wr/peek-poke/src/euclid.rs
@@ -4,107 +4,107 @@
 //
 // 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 crate::{Peek, Poke};
-use euclid::{TypedPoint2D, TypedRect, TypedSideOffsets2D, TypedSize2D, TypedTransform3D, TypedVector2D};
+use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, Vector2D};
 
-unsafe impl<T: Poke, U> Poke for TypedPoint2D<T, U> {
+unsafe impl<T: Poke, U> Poke for Point2D<T, U> {
     #[inline(always)]
     fn max_size() -> usize {
         2 * T::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.x.poke_into(bytes);
         let bytes = self.y.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, U> Peek for TypedPoint2D<T, U> {
+impl<T: Peek, U> Peek for Point2D<T, U> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
         let bytes = T::peek_from(bytes, &mut (*output).x);
         let bytes = T::peek_from(bytes, &mut (*output).y);
         bytes
     }
 }
 
-unsafe impl<T: Poke, U> Poke for TypedRect<T, U> {
+unsafe impl<T: Poke, U> Poke for Rect<T, U> {
     #[inline(always)]
     fn max_size() -> usize {
-        TypedPoint2D::<T, U>::max_size() + TypedSize2D::<T, U>::max_size()
+        Point2D::<T, U>::max_size() + Size2D::<T, U>::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.origin.poke_into(bytes);
         let bytes = self.size.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, U> Peek for TypedRect<T, U> {
+impl<T: Peek, U> Peek for Rect<T, U> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
-        let bytes = TypedPoint2D::<T, U>::peek_from(bytes, &mut (*output).origin);
-        let bytes = TypedSize2D::<T, U>::peek_from(bytes, &mut (*output).size);
+        let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).origin);
+        let bytes = Size2D::<T, U>::peek_from(bytes, &mut (*output).size);
         bytes
     }
 }
 
-unsafe impl<T: Poke, U> Poke for TypedSideOffsets2D<T, U> {
+unsafe impl<T: Poke, U> Poke for SideOffsets2D<T, U> {
     #[inline(always)]
     fn max_size() -> usize {
         4 * T::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.top.poke_into(bytes);
         let bytes = self.right.poke_into(bytes);
         let bytes = self.bottom.poke_into(bytes);
         let bytes = self.left.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, U> Peek for TypedSideOffsets2D<T, U> {
+impl<T: Peek, U> Peek for SideOffsets2D<T, U> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
         let bytes = T::peek_from(bytes, &mut (*output).top);
         let bytes = T::peek_from(bytes, &mut (*output).right);
         let bytes = T::peek_from(bytes, &mut (*output).bottom);
         let bytes = T::peek_from(bytes, &mut (*output).left);
         bytes
     }
 }
 
-unsafe impl<T: Poke, U> Poke for TypedSize2D<T, U> {
+unsafe impl<T: Poke, U> Poke for Size2D<T, U> {
     #[inline(always)]
     fn max_size() -> usize {
         2 * T::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.width.poke_into(bytes);
         let bytes = self.height.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, U> Peek for TypedSize2D<T, U> {
+impl<T: Peek, U> Peek for Size2D<T, U> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
         let bytes = T::peek_from(bytes, &mut (*output).width);
         let bytes = T::peek_from(bytes, &mut (*output).height);
         bytes
     }
 }
 
-unsafe impl<T: Poke, S, D> Poke for TypedTransform3D<T, S, D> {
+unsafe impl<T: Poke, S, D> Poke for Transform3D<T, S, D> {
     #[inline(always)]
     fn max_size() -> usize {
         16 * T::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.m11.poke_into(bytes);
         let bytes = self.m12.poke_into(bytes);
@@ -120,17 +120,17 @@ unsafe impl<T: Poke, S, D> Poke for Type
         let bytes = self.m34.poke_into(bytes);
         let bytes = self.m41.poke_into(bytes);
         let bytes = self.m42.poke_into(bytes);
         let bytes = self.m43.poke_into(bytes);
         let bytes = self.m44.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, S, D> Peek for TypedTransform3D<T, S, D> {
+impl<T: Peek, S, D> Peek for Transform3D<T, S, D> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
         let bytes = T::peek_from(bytes, &mut (*output).m11);
         let bytes = T::peek_from(bytes, &mut (*output).m12);
         let bytes = T::peek_from(bytes, &mut (*output).m13);
         let bytes = T::peek_from(bytes, &mut (*output).m14);
         let bytes = T::peek_from(bytes, &mut (*output).m21);
         let bytes = T::peek_from(bytes, &mut (*output).m22);
@@ -143,28 +143,28 @@ impl<T: Peek, S, D> Peek for TypedTransf
         let bytes = T::peek_from(bytes, &mut (*output).m41);
         let bytes = T::peek_from(bytes, &mut (*output).m42);
         let bytes = T::peek_from(bytes, &mut (*output).m43);
         let bytes = T::peek_from(bytes, &mut (*output).m44);
         bytes
     }
 }
 
-unsafe impl<T: Poke, U> Poke for TypedVector2D<T, U> {
+unsafe impl<T: Poke, U> Poke for Vector2D<T, U> {
     #[inline(always)]
     fn max_size() -> usize {
         2 * T::max_size()
     }
     #[inline(always)]
     unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
         let bytes = self.x.poke_into(bytes);
         let bytes = self.y.poke_into(bytes);
         bytes
     }
 }
-impl<T: Peek, U> Peek for TypedVector2D<T, U> {
+impl<T: Peek, U> Peek for Vector2D<T, U> {
     #[inline(always)]
     unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
         let bytes = T::peek_from(bytes, &mut (*output).x);
         let bytes = T::peek_from(bytes, &mut (*output).y);
         bytes
     }
 }
--- a/gfx/wr/webrender/Cargo.toml
+++ b/gfx/wr/webrender/Cargo.toml
@@ -24,25 +24,25 @@ webrender_build = { version = "0.0.1", p
 
 [dependencies]
 base64 = { optional = true, version = "0.10" }
 bincode = "1.0"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.2"
 cstr = "0.1.2"
-euclid = { version = "0.19.5", features = ["serde"] }
+euclid = { version = "0.20.0", features = ["serde"] }
 fxhash = "0.2.1"
 gleam = "0.6.17"
 image_loader = { optional = true, version = "0.21", package = "image", default-features = false, features = ["png_codec"] }
 lazy_static = "1"
 log = "0.4"
 malloc_size_of_derive = "0.1"
 num-traits = "0.2"
-plane-split = "0.13.7"
+plane-split = "0.14.0"
 png = { optional = true, version = "0.14" }
 rayon = "1"
 ron = { optional = true, version = "0.1.7" }
 serde = { optional = true, version = "1.0", features = ["serde_derive"] }
 serde_json = { optional = true, version = "1.0" }
 sha2 = "0.8"
 smallvec = "0.6"
 thread_profiler = "0.1.1"
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -1331,17 +1331,17 @@ impl BatchBuilder {
                                         let content_uv_rect_address = render_tasks[secondary_id]
                                             .get_texture_address(gpu_cache)
                                             .as_int();
 
                                         for (shadow, shadow_gpu_data) in shadows.iter().zip(picture.extra_gpu_data_handles.iter()) {
                                             // Get the GPU cache address of the extra data handle.
                                             let shadow_prim_address = gpu_cache.get_address(shadow_gpu_data);
 
-                                            let shadow_rect = prim_header.local_rect.translate(&shadow.offset);
+                                            let shadow_rect = prim_header.local_rect.translate(shadow.offset);
 
                                             let shadow_prim_header = PrimitiveHeader {
                                                 local_rect: shadow_rect,
                                                 snap_offsets: prim_info.shadow_snap_offsets,
                                                 specific_prim_address: shadow_prim_address,
                                                 ..prim_header
                                             };
 
@@ -2076,17 +2076,17 @@ impl BatchBuilder {
                     let mut gpu_blocks = Vec::<GpuBlockData>::new();
                     for chunk in image_instance.visible_tiles.chunks(max_tiles_per_header) {
                         gpu_blocks.clear();
                         gpu_blocks.push(PremultipliedColorF::WHITE.into()); //color
                         gpu_blocks.push(PremultipliedColorF::WHITE.into()); //bg color
                         gpu_blocks.push([-1.0, 0.0, 0.0, 0.0].into()); //stretch size
                         // negative first value makes the shader code ignore it and use the local size instead
                         for tile in chunk {
-                            let tile_rect = tile.local_rect.translate(&-prim_rect.origin.to_vector());
+                            let tile_rect = tile.local_rect.translate(-prim_rect.origin.to_vector());
                             gpu_blocks.push(tile_rect.into());
                             gpu_blocks.push(GpuBlockData::EMPTY);
                         }
 
                         let gpu_handle = gpu_cache.push_per_frame_blocks(&gpu_blocks);
                         let prim_header = PrimitiveHeader {
                             local_rect: prim_rect,
                             local_clip_rect: image_instance.tight_local_clip_rect,
@@ -2904,17 +2904,17 @@ impl ClipBatcher {
                 );
                 let normalized_sub_rect = DeviceIntRect::new(
                     p0,
                     DeviceIntSize::new(
                         p1.x - p0.x,
                         p1.y - p0.y,
                     ),
                 ).to_f32();
-                let world_sub_rect = normalized_sub_rect.translate(&mask_origin);
+                let world_sub_rect = normalized_sub_rect.translate(mask_origin);
 
                 // If the clip rect completely contains this tile rect, then drawing
                 // these pixels would be redundant - since this clip can't possibly
                 // affect the pixels in this tile, skip them!
                 if !world_device_rect.contains_rect(&world_sub_rect) {
                     clip_list.slow_rectangles.push(ClipMaskInstance {
                         clip_data_address: gpu_address,
                         sub_rect: normalized_sub_rect,
--- a/gfx/wr/webrender/src/border.rs
+++ b/gfx/wr/webrender/src/border.rs
@@ -1067,17 +1067,17 @@ fn add_corner_segment(
     let segment_rect = image_rect.intersection(&non_overlapping_rect)
         .unwrap_or_else(LayoutRect::zero);
 
     if segment_rect.size.width <= 0. || segment_rect.size.height <= 0. {
         return;
     }
 
     let texture_rect = segment_rect
-        .translate(&-image_rect.origin.to_vector())
+        .translate(-image_rect.origin.to_vector())
         .scale(1.0 / image_rect.size.width, 1.0 / image_rect.size.height);
 
     brush_segments.push(
         BrushSegment::new(
             segment_rect,
             /* may_need_clip_mask = */ true,
             edge_flags,
             [texture_rect.min_x(), texture_rect.min_y(), texture_rect.max_x(), texture_rect.max_y()],
--- a/gfx/wr/webrender/src/box_shadow.rs
+++ b/gfx/wr/webrender/src/box_shadow.rs
@@ -95,17 +95,17 @@ impl<'a> DisplayListFlattener<'a> {
 
         // Adjust the border radius of the box shadow per CSS-spec.
         let shadow_radius = adjust_border_radius_for_box_shadow(border_radius, spread_amount);
 
         // Apply parameters that affect where the shadow rect
         // exists in the local space of the primitive.
         let shadow_rect = prim_info
             .rect
-            .translate(box_offset)
+            .translate(*box_offset)
             .inflate(spread_amount, spread_amount);
 
         // If blur radius is zero, we can use a fast path with
         // no blur applied.
         if blur_radius == 0.0 {
             // Trivial reject of box-shadows that are not visible.
             if box_offset.x == 0.0 && box_offset.y == 0.0 && spread_amount == 0.0 {
                 return;
@@ -196,17 +196,17 @@ impl<'a> DisplayListFlattener<'a> {
             let prim = PrimitiveKeyKind::Rectangle {
                 color: color.into(),
             };
 
             // Create the box-shadow clip item.
             let shadow_clip_source = ClipItemKey::box_shadow(
                 shadow_rect,
                 shadow_radius,
-                dest_rect.translate(&LayoutVector2D::new(-prim_info.rect.origin.x, -prim_info.rect.origin.y)),
+                dest_rect.translate(LayoutVector2D::new(-prim_info.rect.origin.x, -prim_info.rect.origin.y)),
                 blur_radius,
                 clip_mode,
             );
 
             let prim_info = match clip_mode {
                 BoxShadowClipMode::Outset => {
                     // Certain spread-radii make the shadow invalid.
                     if !shadow_rect.is_well_formed_and_nonempty() {
--- a/gfx/wr/webrender/src/clip.rs
+++ b/gfx/wr/webrender/src/clip.rs
@@ -953,17 +953,17 @@ pub struct ComplexTranslateIter<I> {
 }
 
 impl<I: Iterator<Item = ComplexClipRegion>> Iterator for ComplexTranslateIter<I> {
     type Item = ComplexClipRegion;
     fn next(&mut self) -> Option<Self::Item> {
         self.source
             .next()
             .map(|mut complex| {
-                complex.rect = complex.rect.translate(&self.offset);
+                complex.rect = complex.rect.translate(self.offset);
                 complex
             })
     }
 }
 
 #[derive(Clone, Debug)]
 pub struct ClipRegion<I> {
     pub main: LayoutRect,
@@ -977,37 +977,37 @@ impl<J> ClipRegion<ComplexTranslateIter<
         complex_clips: J,
         mut image_mask: Option<ImageMask>,
         reference_frame_relative_offset: &LayoutVector2D,
     ) -> Self
     where
         J: Iterator<Item = ComplexClipRegion>
     {
         if let Some(ref mut image_mask) = image_mask {
-            image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
+            image_mask.rect = image_mask.rect.translate(*reference_frame_relative_offset);
         }
 
         ClipRegion {
-            main: rect.translate(reference_frame_relative_offset),
+            main: rect.translate(*reference_frame_relative_offset),
             image_mask,
             complex_clips: ComplexTranslateIter {
                 source: complex_clips,
                 offset: *reference_frame_relative_offset,
             },
         }
     }
 }
 
 impl ClipRegion<Option<ComplexClipRegion>> {
     pub fn create_for_clip_node_with_local_clip(
         local_clip: &LayoutRect,
         reference_frame_relative_offset: &LayoutVector2D
     ) -> Self {
         ClipRegion {
-            main: local_clip.translate(reference_frame_relative_offset),
+            main: local_clip.translate(*reference_frame_relative_offset),
             image_mask: None,
             complex_clips: None,
         }
     }
 }
 
 // The ClipItemKey is a hashable representation of the contents
 // of a clip item. It is used during interning to de-duplicate
@@ -1489,17 +1489,17 @@ impl From<LayoutRect> for Geometry {
     }
 }
 
 pub fn rounded_rectangle_contains_point(
     point: &LayoutPoint,
     rect: &LayoutRect,
     radii: &BorderRadius
 ) -> bool {
-    if !rect.contains(point) {
+    if !rect.contains(*point) {
         return false;
     }
 
     let top_left_center = rect.origin + radii.top_left.to_vector();
     if top_left_center.x > point.x && top_left_center.y > point.y &&
        !Ellipse::new(radii.top_left).contains(*point - top_left_center.to_vector()) {
         return false;
     }
@@ -1527,20 +1527,20 @@ pub fn rounded_rectangle_contains_point(
     true
 }
 
 pub fn project_inner_rect(
     transform: &LayoutToWorldTransform,
     rect: &LayoutRect,
 ) -> Option<WorldRect> {
     let points = [
-        transform.transform_point2d(&rect.origin)?,
-        transform.transform_point2d(&rect.top_right())?,
-        transform.transform_point2d(&rect.bottom_left())?,
-        transform.transform_point2d(&rect.bottom_right())?,
+        transform.transform_point2d(rect.origin)?,
+        transform.transform_point2d(rect.top_right())?,
+        transform.transform_point2d(rect.bottom_left())?,
+        transform.transform_point2d(rect.bottom_right())?,
     ];
 
     let mut xs = [points[0].x, points[1].x, points[2].x, points[3].x];
     let mut ys = [points[0].y, points[1].y, points[2].y, points[3].y];
     xs.sort_by(|a, b| a.partial_cmp(b).unwrap_or(cmp::Ordering::Equal));
     ys.sort_by(|a, b| a.partial_cmp(b).unwrap_or(cmp::Ordering::Equal));
     Some(WorldRect::new(
         WorldPoint::new(xs[1], ys[1]),
--- a/gfx/wr/webrender/src/clip_scroll_tree.rs
+++ b/gfx/wr/webrender/src/clip_scroll_tree.rs
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{ExternalScrollId, PropertyBinding, ReferenceFrameKind, TransformStyle};
 use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
 use api::units::*;
-use euclid::TypedTransform3D;
+use euclid::Transform3D;
 use crate::gpu_types::TransformPalette;
 use crate::internal_types::{FastHashMap, FastHashSet};
 use crate::print_tree::{PrintableTree, PrintTree, PrintTreePrinter};
 use crate::scene::SceneProperties;
 use crate::spatial_node::{ScrollFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo, ScrollFrameKind};
 use std::{ops, u32};
 use crate::util::{FastTransform, LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset, scale_factors};
 
@@ -141,23 +141,23 @@ pub struct TransformUpdateState {
 
 
 /// Transformation between two nodes in the clip-scroll tree that can sometimes be
 /// encoded more efficiently than with a full matrix.
 #[derive(Debug, Clone)]
 pub enum CoordinateSpaceMapping<Src, Dst> {
     Local,
     ScaleOffset(ScaleOffset),
-    Transform(TypedTransform3D<f32, Src, Dst>),
+    Transform(Transform3D<f32, Src, Dst>),
 }
 
 impl<Src, Dst> CoordinateSpaceMapping<Src, Dst> {
-    pub fn into_transform(self) -> TypedTransform3D<f32, Src, Dst> {
+    pub fn into_transform(self) -> Transform3D<f32, Src, Dst> {
         match self {
-            CoordinateSpaceMapping::Local => TypedTransform3D::identity(),
+            CoordinateSpaceMapping::Local => Transform3D::identity(),
             CoordinateSpaceMapping::ScaleOffset(scale_offset) => scale_offset.to_transform(),
             CoordinateSpaceMapping::Transform(transform) => transform,
         }
     }
 
     pub fn into_fast_transform(self) -> FastTransform<Src, Dst> {
         match self {
             CoordinateSpaceMapping::Local => FastTransform::identity(),
@@ -282,20 +282,20 @@ impl ClipScrollTree {
         while coordinate_system_id != parent.coordinate_system_id {
             let coord_system = &self.coord_systems[coordinate_system_id.0 as usize];
 
             if coord_system.should_flatten {
                 transform.flatten_z_output();
             }
 
             coordinate_system_id = coord_system.parent.expect("invalid parent!");
-            transform = transform.post_mul(&coord_system.transform);
+            transform = transform.post_transform(&coord_system.transform);
         }
 
-        transform = transform.post_mul(
+        transform = transform.post_transform(
             &parent.content_transform
                 .inverse()
                 .to_transform(),
         );
 
         CoordinateSpaceMapping::Transform(transform)
     }
 
@@ -315,17 +315,17 @@ impl ClipScrollTree {
         } else {
             let system = &self.coord_systems[child.coordinate_system_id.0 as usize];
             let scale_offset = match scroll {
                 TransformScroll::Scrolled => &child.content_transform,
                 TransformScroll::Unscrolled => &child.viewport_transform,
             };
             let transform = scale_offset
                 .to_transform()
-                .post_mul(&system.world_transform);
+                .post_transform(&system.world_transform);
 
             CoordinateSpaceMapping::Transform(transform)
         }
     }
 
     /// Calculate the relative transform from `index` to the root.
     pub fn get_world_transform(
         &self,
@@ -710,17 +710,17 @@ fn test_pt(
     expected_x: f32,
     expected_y: f32,
 ) {
     use euclid::approxeq::ApproxEq;
     const EPSILON: f32 = 0.0001;
 
     let p = LayoutPoint::new(px, py);
     let m = cst.get_relative_transform(child, parent).into_transform();
-    let pt = m.transform_point2d(&p).unwrap();
+    let pt = m.transform_point2d(p).unwrap();
     assert!(pt.x.approx_eq_eps(&expected_x, &EPSILON) &&
             pt.y.approx_eq_eps(&expected_y, &EPSILON),
             "p: {:?} -> {:?}\nm={:?}",
             p, pt, m,
             );
 }
 
 #[test]
--- a/gfx/wr/webrender/src/debug_render.rs
+++ b/gfx/wr/webrender/src/debug_render.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{ColorU, ColorF, ImageFormat, TextureTarget};
 use api::units::*;
 use crate::debug_font_data;
 use crate::device::{Device, Program, Texture, TextureSlot, VertexDescriptor, ShaderError, VAO};
 use crate::device::{TextureFilter, VertexAttribute, VertexAttributeKind, VertexUsageHint};
-use euclid::{Point2D, Rect, Size2D, Transform3D};
+use euclid::{Point2D, Rect, Size2D, Transform3D, default};
 use crate::internal_types::{ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE};
 use std::f32;
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum DebugItem {
     Text {
         msg: String,
@@ -188,17 +188,17 @@ impl DebugRenderer {
     /// this file.
     pub fn add_text(
         &mut self,
         x: f32,
         y: f32,
         text: &str,
         color: ColorU,
         bounds: Option<DeviceRect>,
-    ) -> Rect<f32> {
+    ) -> default::Rect<f32> {
         let mut x_start = x;
         let ipw = 1.0 / debug_font_data::BMP_WIDTH as f32;
         let iph = 1.0 / debug_font_data::BMP_HEIGHT as f32;
 
         let mut min_x = f32::MAX;
         let mut max_x = -f32::MAX;
         let mut min_y = f32::MAX;
         let mut max_y = -f32::MAX;
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use super::super::shader_source::SHADERS;
 use api::{ColorF, ImageDescriptor, ImageFormat, MemoryReport};
 use api::{MixBlendMode, TextureTarget, VoidPtrToSizeFn};
 use api::units::*;
-use euclid::Transform3D;
+use euclid::default::Transform3D;
 use gleam::gl;
 use crate::internal_types::{FastHashMap, LayerIndex, RenderTargetInfo};
 use log::Level;
 use crate::profiler;
 use sha2::{Digest, Sha256};
 use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
@@ -1040,17 +1040,17 @@ pub enum DrawTarget {
     External {
         fbo: FBOId,
         size: FramebufferIntSize,
     },
 }
 
 impl DrawTarget {
     pub fn new_default(size: DeviceIntSize) -> Self {
-        let total_size = FramebufferIntSize::from_untyped(&size.to_untyped());
+        let total_size = FramebufferIntSize::from_untyped(size.to_untyped());
         DrawTarget::Default {
             rect: total_size.into(),
             total_size,
         }
     }
 
     /// Returns true if this draw target corresponds to the default framebuffer.
     pub fn is_default(&self) -> bool {
@@ -1080,19 +1080,19 @@ impl DrawTarget {
             id: texture.id,
             target: texture.target,
         }
     }
 
     /// Returns the dimensions of this draw-target.
     pub fn dimensions(&self) -> DeviceIntSize {
         match *self {
-            DrawTarget::Default { total_size, .. } => DeviceIntSize::from_untyped(&total_size.to_untyped()),
+            DrawTarget::Default { total_size, .. } => DeviceIntSize::from_untyped(total_size.to_untyped()),
             DrawTarget::Texture { dimensions, .. } => dimensions,
-            DrawTarget::External { size, .. } => DeviceIntSize::from_untyped(&size.to_untyped()),
+            DrawTarget::External { size, .. } => DeviceIntSize::from_untyped(size.to_untyped()),
         }
     }
 
     pub fn to_framebuffer_rect(&self, device_rect: DeviceIntRect) -> FramebufferIntRect {
         let mut fb_rect = FramebufferIntRect::from_untyped(&device_rect.to_untyped());
         match *self {
             DrawTarget::Default { ref rect, .. } => {
                 // perform a Y-flip here
@@ -1112,28 +1112,28 @@ impl DrawTarget {
         scissor_rect: Option<DeviceIntRect>,
         content_origin: DeviceIntPoint,
     ) -> FramebufferIntRect {
         let dimensions = self.dimensions();
 
         match scissor_rect {
             Some(scissor_rect) => match *self {
                 DrawTarget::Default { ref rect, .. } => {
-                    self.to_framebuffer_rect(scissor_rect.translate(&-content_origin.to_vector()))
+                    self.to_framebuffer_rect(scissor_rect.translate(-content_origin.to_vector()))
                         .intersection(rect)
                         .unwrap_or_else(FramebufferIntRect::zero)
                 }
                 DrawTarget::Texture { .. } | DrawTarget::External { .. } => {
                     FramebufferIntRect::from_untyped(&scissor_rect.to_untyped())
                 }
             }
             None => {
                 FramebufferIntRect::new(
                     FramebufferIntPoint::zero(),
-                    FramebufferIntSize::from_untyped(&dimensions.to_untyped()),
+                    FramebufferIntSize::from_untyped(dimensions.to_untyped()),
                 )
             }
         }
     }
 }
 
 /// Contains the parameters necessary to bind a texture-backed read target.
 #[derive(Clone, Copy)]
@@ -1594,17 +1594,17 @@ impl Device {
         &mut self,
         target: DrawTarget,
     ) {
         let (fbo_id, rect, depth_available) = match target {
             DrawTarget::Default { rect, .. } => (self.default_draw_fbo, rect, true),
             DrawTarget::Texture { dimensions, fbo_id, with_depth, .. } => {
                 let rect = FramebufferIntRect::new(
                     FramebufferIntPoint::zero(),
-                    FramebufferIntSize::from_untyped(&dimensions.to_untyped()),
+                    FramebufferIntSize::from_untyped(dimensions.to_untyped()),
                 );
                 (fbo_id, rect, with_depth)
             },
             DrawTarget::External { fbo, size } => (fbo, size.into(), false),
         };
 
         self.depth_available = depth_available;
         self.bind_draw_target_impl(fbo_id);
@@ -1999,17 +1999,17 @@ impl Device {
                                             0, 0, 0,
                                             dst.id, dst.target, 0,
                                             0, 0, 0,
                                             src.size.width as _, src.size.height as _, src.layer_count);
             }
         } else {
             let rect = FramebufferIntRect::new(
                 FramebufferIntPoint::zero(),
-                FramebufferIntSize::from_untyped(&src.get_dimensions().to_untyped()),
+                FramebufferIntSize::from_untyped(src.get_dimensions().to_untyped()),
             );
             for layer in 0..src.layer_count.min(dst.layer_count) as LayerIndex {
                 self.blit_render_target(
                     ReadTarget::from_texture(src, layer),
                     rect,
                     DrawTarget::from_texture(dst, layer, false),
                     rect,
                     TextureFilter::Linear
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -699,17 +699,17 @@ impl<'a> DisplayListFlattener<'a> {
     }
 
     fn flatten_sticky_frame(
         &mut self,
         info: &StickyFrameDisplayItem,
         parent_node_index: SpatialNodeIndex,
     ) {
         let current_offset = self.current_offset(parent_node_index);
-        let frame_rect = info.bounds.translate(&current_offset);
+        let frame_rect = info.bounds.translate(current_offset);
         let sticky_frame_info = StickyFrameInfo::new(
             frame_rect,
             info.margins,
             info.vertical_offset_bounds,
             info.horizontal_offset_bounds,
             info.previously_applied_offset,
         );
 
@@ -961,18 +961,18 @@ impl<'a> DisplayListFlattener<'a> {
         let clip_and_scroll = self.get_clip_and_scroll(
             &common.clip_id,
             &common.spatial_id,
             apply_pipeline_clip
         );
 
         let current_offset = self.current_offset(clip_and_scroll.spatial_node_index);
 
-        let clip_rect = common.clip_rect.translate(&current_offset);
-        let rect = bounds.translate(&current_offset);
+        let clip_rect = common.clip_rect.translate(current_offset);
+        let rect = bounds.translate(current_offset);
         let layout = LayoutPrimitiveInfo {
             rect,
             clip_rect,
             is_backface_visible: common.is_backface_visible,
             hit_info: common.hit_info,
         };
 
         (layout, clip_and_scroll)
@@ -2525,19 +2525,19 @@ impl<'a> DisplayListFlattener<'a> {
         prims: &mut Vec<PrimitiveInstance>,
     )
     where
         P: InternablePrimitive + CreateShadow,
         Interners: AsMut<Interner<P>>,
     {
         // Offset the local rect and clip rect by the shadow offset.
         let mut info = pending_primitive.info.clone();
-        info.rect = info.rect.translate(&pending_shadow.shadow.offset);
+        info.rect = info.rect.translate(pending_shadow.shadow.offset);
         info.clip_rect = info.clip_rect.translate(
-            &pending_shadow.shadow.offset
+            pending_shadow.shadow.offset
         );
 
         // Construct and add a primitive for the given shadow.
         let shadow_prim_instance = self.create_primitive(
             &info,
             pending_primitive.clip_and_scroll.clip_chain_id,
             pending_primitive.clip_and_scroll.spatial_node_index,
             pending_primitive.prim.create_shadow(&pending_shadow.shadow),
--- a/gfx/wr/webrender/src/ellipse.rs
+++ b/gfx/wr/webrender/src/ellipse.rs
@@ -1,29 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::units::*;
-use euclid::TypedSize2D;
+use euclid::Size2D;
 use std::f32::consts::FRAC_PI_2;
 
 
 /// Number of steps to integrate arc length over.
 const STEP_COUNT: usize = 20;
 
 /// Represents an ellipse centred at a local space origin.
 #[derive(Debug, Clone)]
 pub struct Ellipse<U> {
-    pub radius: TypedSize2D<f32, U>,
+    pub radius: Size2D<f32, U>,
     pub total_arc_length: f32,
 }
 
 impl<U> Ellipse<U> {
-    pub fn new(radius: TypedSize2D<f32, U>) -> Ellipse<U> {
+    pub fn new(radius: Size2D<f32, U>) -> Ellipse<U> {
         // Approximate the total length of the first quadrant of this ellipse.
         let total_arc_length = get_simpson_length(FRAC_PI_2, radius.width, radius.height);
 
         Ellipse {
             radius,
             total_arc_length,
         }
     }
--- a/gfx/wr/webrender/src/gpu_cache.rs
+++ b/gfx/wr/webrender/src/gpu_cache.rs
@@ -23,17 +23,17 @@
 //! use the ```get_address``` API to get the allocated
 //! address in the GPU cache of a given resource slot
 //! for this frame.
 
 use api::{DebugFlags, DocumentId, PremultipliedColorF};
 #[cfg(test)]
 use api::IdNamespace;
 use api::units::TexelRect;
-use euclid::{HomogeneousVector, TypedRect};
+use euclid::{HomogeneousVector, Rect};
 use crate::internal_types::{FastHashMap, FastHashSet};
 use crate::profiler::GpuCacheProfileCounters;
 use crate::render_backend::{FrameStamp, FrameId};
 use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH;
 use std::{mem, u16, u32};
 use std::num::NonZeroU32;
 use std::ops::Add;
 use std::time::{Duration, Instant};
@@ -97,18 +97,18 @@ impl From<PremultipliedColorF> for GpuBl
 }
 
 impl From<[f32; 4]> for GpuBlockData {
     fn from(data: [f32; 4]) -> Self {
         GpuBlockData { data }
     }
 }
 
-impl<P> From<TypedRect<f32, P>> for GpuBlockData {
-    fn from(r: TypedRect<f32, P>) -> Self {
+impl<P> From<Rect<f32, P>> for GpuBlockData {
+    fn from(r: Rect<f32, P>) -> Self {
         GpuBlockData {
             data: [
                 r.origin.x,
                 r.origin.y,
                 r.size.width,
                 r.size.height,
             ],
         }
--- a/gfx/wr/webrender/src/hit_test.rs
+++ b/gfx/wr/webrender/src/hit_test.rs
@@ -192,19 +192,19 @@ enum HitTestRegion {
     Rectangle(LayoutRect, ClipMode),
     RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
 }
 
 impl HitTestRegion {
     pub fn contains(&self, point: &LayoutPoint) -> bool {
         match *self {
             HitTestRegion::Rectangle(ref rectangle, ClipMode::Clip) =>
-                rectangle.contains(point),
+                rectangle.contains(*point),
             HitTestRegion::Rectangle(ref rectangle, ClipMode::ClipOut) =>
-                !rectangle.contains(point),
+                !rectangle.contains(*point),
             HitTestRegion::RoundedRectangle(rect, radii, ClipMode::Clip) =>
                 rounded_rectangle_contains_point(point, &rect, &radii),
             HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
                 !rounded_rectangle_contains_point(point, &rect, &radii),
             HitTestRegion::Invalid => true,
         }
     }
 }
@@ -337,17 +337,17 @@ impl HitTester {
         }
 
         let node = &self.clip_chains[clip_chain_node_id.0 as usize].region;
         let transform = self
             .spatial_nodes[spatial_node_index.0 as usize]
             .world_content_transform;
         let transformed_point = match transform
             .inverse()
-            .and_then(|inverted| inverted.transform_point2d(&point))
+            .and_then(|inverted| inverted.transform_point2d(point))
         {
             Some(point) => point,
             None => {
                 test.node_cache.insert(clip_chain_node_id, ClippedIn::NotClippedIn);
                 return false;
             }
         };
 
@@ -370,29 +370,29 @@ impl HitTester {
             let scroll_node = &self.spatial_nodes[item.spatial_node_index.0 as usize];
 
             // Update the cached point in layer space, if the spatial node
             // changed since last primitive.
             if item.spatial_node_index != current_spatial_node_index {
                 point_in_layer = scroll_node
                     .world_content_transform
                     .inverse()
-                    .and_then(|inverted| inverted.transform_point2d(&point));
+                    .and_then(|inverted| inverted.transform_point2d(point));
 
                 current_spatial_node_index = item.spatial_node_index;
             }
 
             // Only consider hit tests on transformable layers.
             if let Some(point_in_layer) = point_in_layer {
                 // If the item's rect or clip rect don't contain this point,
                 // it's not a valid hit.
-                if !item.rect.contains(&point_in_layer) {
+                if !item.rect.contains(point_in_layer) {
                     continue;
                 }
-                if !item.clip_rect.contains(&point_in_layer) {
+                if !item.clip_rect.contains(point_in_layer) {
                     continue;
                 }
 
                 // See if any of the clip chain roots for this primitive
                 // cull out the item.
                 let clip_chains = self.scene.get_clip_chains_for_item(item);
                 let mut is_valid = true;
                 for clip_chain_id in clip_chains {
@@ -431,28 +431,28 @@ impl HitTester {
             }
 
             // Update the cached point in layer space, if the spatial node
             // changed since last primitive.
             if item.spatial_node_index != current_spatial_node_index {
                 point_in_layer = scroll_node
                     .world_content_transform
                     .inverse()
-                    .and_then(|inverted| inverted.transform_point2d(&point));
+                    .and_then(|inverted| inverted.transform_point2d(point));
                 current_spatial_node_index = item.spatial_node_index;
             }
 
             // Only consider hit tests on transformable layers.
             if let Some(point_in_layer) = point_in_layer {
                 // If the item's rect or clip rect don't contain this point,
                 // it's not a valid hit.
-                if !item.rect.contains(&point_in_layer) {
+                if !item.rect.contains(point_in_layer) {
                     continue;
                 }
-                if !item.clip_rect.contains(&point_in_layer) {
+                if !item.clip_rect.contains(point_in_layer) {
                     continue;
                 }
 
                 // See if any of the clip chain roots for this primitive
                 // cull out the item.
                 let clip_chains = self.scene.get_clip_chains_for_item(item);
                 let mut is_valid = true;
                 for clip_chain_id in clip_chains {
@@ -475,17 +475,17 @@ impl HitTester {
                 // in a situation with an uninvertible transformation so we should just skip this
                 // result.
                 let root_spatial_node_index = self.pipeline_root_nodes[&pipeline_id];
                 if root_spatial_node_index != current_root_spatial_node_index {
                     let root_node = &self.spatial_nodes[root_spatial_node_index.0 as usize];
                     point_in_viewport = root_node
                         .world_viewport_transform
                         .inverse()
-                        .and_then(|inverted| inverted.transform_point2d(&point))
+                        .and_then(|inverted| inverted.transform_point2d(point))
                         .map(|pt| pt - scroll_node.external_scroll_offset);
 
                     current_root_spatial_node_index = root_spatial_node_index;
                 }
 
                 if let Some(point_in_viewport) = point_in_viewport {
                     result.items.push(HitTestItem {
                         pipeline: pipeline_id,
@@ -557,17 +557,17 @@ impl HitTest {
         self.clip_chain_cache[index] = Some(value);
     }
 
     fn get_absolute_point(&self, hit_tester: &HitTester) -> WorldPoint {
         if !self.flags.contains(HitTestFlags::POINT_RELATIVE_TO_PIPELINE_VIEWPORT) {
             return self.point;
         }
 
-        let point =  &LayoutPoint::new(self.point.x, self.point.y);
+        let point = LayoutPoint::new(self.point.x, self.point.y);
         self.pipeline_id
             .and_then(|id|
                 hit_tester
                     .get_pipeline_root(id)
                     .world_viewport_transform
                     .transform_point2d(point)
             )
             .unwrap_or_else(|| {
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -7,17 +7,17 @@ use api::{PropertyBinding, PropertyBindi
 use api::{DebugFlags, RasterSpace, ImageKey, ColorF};
 use api::units::*;
 use crate::box_shadow::{BLUR_SAMPLE_SCALE};
 use crate::clip::{ClipStore, ClipDataStore, ClipChainInstance};
 use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX,
     ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace, CoordinateSystemId
 };
 use crate::debug_colors;
-use euclid::{vec3, TypedPoint2D, TypedScale, TypedSize2D, Vector2D, TypedRect};
+use euclid::{vec3, Point2D, Scale, Size2D, Vector2D, Rect};
 use euclid::approxeq::ApproxEq;
 use crate::filterdata::SFilterData;
 use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
 use crate::intern::ItemUid;
 use crate::internal_types::{FastHashMap, FastHashSet, PlaneSplitter, Filter};
 use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
 use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use crate::gpu_types::UvRectKind;
@@ -134,19 +134,19 @@ impl RetainedTiles {
     }
 }
 
 /// Unit for tile coordinates.
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct TileCoordinate;
 
 // Geometry types for tile coordinates.
-pub type TileOffset = TypedPoint2D<i32, TileCoordinate>;
-pub type TileSize = TypedSize2D<i32, TileCoordinate>;
-pub type TileRect = TypedRect<i32, TileCoordinate>;
+pub type TileOffset = Point2D<i32, TileCoordinate>;
+pub type TileSize = Size2D<i32, TileCoordinate>;
+pub type TileRect = Rect<i32, TileCoordinate>;
 
 /// The size in device pixels of a cached tile. The currently chosen
 /// size is arbitrary. We should do some profiling to find the best
 /// size for real world pages.
 ///
 /// Note that we use a separate, smaller size during wrench testing, so that
 /// we get tighter dirty rects and can do more meaningful invalidation
 /// tests.
@@ -1608,17 +1608,17 @@ impl PictureCompositeMode {
                             let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
                             let inflation_factor = primitive.radius.round() * BLUR_SAMPLE_SCALE;
                             input.inflate(inflation_factor, inflation_factor)
                         }
                         FilterPrimitiveKind::DropShadow(ref primitive) => {
                             let inflation_factor = primitive.shadow.blur_radius.round() * BLUR_SAMPLE_SCALE;
                             let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
                             let shadow_rect = input.inflate(inflation_factor, inflation_factor);
-                            input.union(&shadow_rect.translate(&(primitive.shadow.offset * TypedScale::new(1.0))))
+                            input.union(&shadow_rect.translate(primitive.shadow.offset * Scale::new(1.0)))
                         }
                         FilterPrimitiveKind::Blend(ref primitive) => {
                             primitive.input1.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect)
                                 .union(&primitive.input2.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect))
                         }
                         FilterPrimitiveKind::Identity(ref primitive) =>
                             primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect),
                         FilterPrimitiveKind::Opacity(ref primitive) =>
@@ -2686,17 +2686,17 @@ impl PicturePrimitive {
             Some(rect) => rect.cast(),
             None => return false,
         };
         let world_rect = world_rect.cast();
 
         match transform {
             CoordinateSpaceMapping::Local => {
                 let polygon = Polygon::from_rect(
-                    local_rect * TypedScale::new(1.0),
+                    local_rect * Scale::new(1.0),
                     plane_split_anchor,
                 );
                 splitter.add(polygon);
             }
             CoordinateSpaceMapping::ScaleOffset(scale_offset) if scale_offset.scale == Vector2D::new(1.0, 1.0) => {
                 let inv_matrix = scale_offset.inverse().to_transform().cast();
                 let polygon = Polygon::from_transformed_rect_with_inverse(
                     local_rect,
@@ -2749,20 +2749,20 @@ impl PicturePrimitive {
                 .inverse()
             {
                 Some(transform) => transform.into_transform(),
                 // logging this would be a bit too verbose
                 None => continue,
             };
 
             let local_points = [
-                transform.transform_point3d(&poly.points[0].cast()).unwrap(),
-                transform.transform_point3d(&poly.points[1].cast()).unwrap(),
-                transform.transform_point3d(&poly.points[2].cast()).unwrap(),
-                transform.transform_point3d(&poly.points[3].cast()).unwrap(),
+                transform.transform_point3d(poly.points[0].cast()).unwrap(),
+                transform.transform_point3d(poly.points[1].cast()).unwrap(),
+                transform.transform_point3d(poly.points[2].cast()).unwrap(),
+                transform.transform_point3d(poly.points[3].cast()).unwrap(),
             ];
             let gpu_blocks = [
                 [local_points[0].x, local_points[0].y, local_points[1].x, local_points[1].y].into(),
                 [local_points[2].x, local_points[2].y, local_points[3].x, local_points[3].y].into(),
             ];
             let gpu_handle = gpu_cache.push_per_frame_blocks(&gpu_blocks);
             let gpu_address = gpu_cache.get_address(&gpu_handle);
 
@@ -2956,17 +2956,17 @@ impl PicturePrimitive {
         // rect into the parent surface coordinate space, and propagate that up
         // to the parent.
         if let Some(ref mut raster_config) = self.raster_config {
             let surface = state.current_surface_mut();
             // Inflate the local bounding rect if required by the filter effect.
             // This inflaction factor is to be applied to the surface itself.
             surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.inflation_factor);
 
-            let mut surface_rect = surface.rect * TypedScale::new(1.0);
+            let mut surface_rect = surface.rect * Scale::new(1.0);
 
             // Pop this surface from the stack
             let surface_index = state.pop_surface();
             debug_assert_eq!(surface_index, raster_config.surface_index);
 
             // Snapping may change the local rect slightly, and as such should just be
             // considered an estimated size for determining if we need raster roots and
             // preparing the tile cache.
@@ -2983,17 +2983,17 @@ impl PicturePrimitive {
             }
 
             // Drop shadows draw both a content and shadow rect, so need to expand the local
             // rect of any surfaces to be composited in parent surfaces correctly.
             match raster_config.composite_mode {
                 PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
                     for shadow in shadows {
                         let content_rect = surface_rect;
-                        let shadow_rect = surface_rect.translate(&shadow.offset);
+                        let shadow_rect = surface_rect.translate(shadow.offset);
                         surface_rect = content_rect.union(&shadow_rect);
                     }
                 }
                 _ => {}
             }
 
             // Propagate up to parent surface, now that we know this surface's static rect
             let parent_surface = state.current_surface_mut();
@@ -3045,17 +3045,17 @@ impl PicturePrimitive {
             PictureCompositeMode::Filter(Filter::Blur(..)) => {}
             PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
                 self.extra_gpu_data_handles.resize(shadows.len(), GpuCacheHandle::new());
                 for (shadow, extra_handle) in shadows.iter().zip(self.extra_gpu_data_handles.iter_mut()) {
                     if let Some(mut request) = frame_state.gpu_cache.request(extra_handle) {
                         // Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs)
                         //  [brush specific data]
                         //  [segment_rect, segment data]
-                        let shadow_rect = self.snapped_local_rect.translate(&shadow.offset);
+                        let shadow_rect = self.snapped_local_rect.translate(shadow.offset);
 
                         // ImageBrush colors
                         request.push(shadow.color.premultiplied());
                         request.push(PremultipliedColorF::WHITE);
                         request.push([
                             self.snapped_local_rect.size.width,
                             self.snapped_local_rect.size.height,
                             0.0,
@@ -3108,17 +3108,17 @@ impl PicturePrimitive {
 // Calculate a single homogeneous screen-space UV for a picture.
 fn calculate_screen_uv(
     local_pos: &PicturePoint,
     transform: &PictureToRasterTransform,
     rendered_rect: &DeviceRect,
     device_pixel_scale: DevicePixelScale,
     supports_snapping: bool,
 ) -> DeviceHomogeneousVector {
-    let raster_pos = transform.transform_point2d_homogeneous(local_pos);
+    let raster_pos = transform.transform_point2d_homogeneous(*local_pos);
 
     let mut device_vec = DeviceHomogeneousVector::new(
         raster_pos.x * device_pixel_scale.0,
         raster_pos.y * device_pixel_scale.0,
         0.0,
         raster_pos.w,
     );
 
--- a/gfx/wr/webrender/src/platform/macos/font.rs
+++ b/gfx/wr/webrender/src/platform/macos/font.rs
@@ -17,17 +17,17 @@ use core_graphics::context::CGContext;
 use core_graphics::context::{CGBlendMode, CGTextDrawingMode};
 use core_graphics::data_provider::CGDataProvider;
 use core_graphics::font::{CGFont, CGGlyph};
 use core_graphics::geometry::{CGAffineTransform, CGPoint, CGSize};
 use core_graphics::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGRect};
 use core_text;
 use core_text::font::{CTFont, CTFontRef};
 use core_text::font_descriptor::{kCTFontDefaultOrientation, kCTFontColorGlyphsTrait};
-use euclid::Size2D;
+use euclid::default::Size2D;
 use crate::gamma_lut::{ColorLut, GammaLut};
 use crate::glyph_rasterizer::{FontInstance, FontTransform, GlyphKey};
 use crate::glyph_rasterizer::{GlyphFormat, GlyphRasterError, GlyphRasterResult, RasterizedGlyph};
 use crate::internal_types::{FastHashMap, ResourceCacheError};
 use std::collections::hash_map::Entry;
 use std::sync::Arc;
 
 const INITIAL_CG_CONTEXT_SIDE_LENGTH: u32 = 32;
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -11,17 +11,17 @@ use api::units::*;
 use crate::border::{get_max_scale_for_border, build_border_instances};
 use crate::border::BorderSegmentCacheKey;
 use crate::clip::{ClipStore};
 use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace};
 use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance, ClipItem};
 use crate::debug_colors;
 use crate::debug_render::DebugItem;
 use crate::display_list_flattener::{CreateShadow, IsVisible};
-use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D, TypedPoint2D};
+use euclid::{SideOffsets2D, Transform3D, Rect, Scale, Size2D, Point2D};
 use euclid::approxeq::ApproxEq;
 use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
 use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
 use crate::glyph_rasterizer::GlyphKey;
 use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpuBlocks};
 use crate::gpu_types::{BrushFlags, SnapOffsets};
 use crate::image::{Repetition};
 use crate::intern;
@@ -129,38 +129,38 @@ impl PrimitiveOpacity {
 }
 
 
 #[derive(Debug, Clone)]
 pub struct SpaceMapper<F, T> {
     kind: CoordinateSpaceMapping<F, T>,
     pub ref_spatial_node_index: SpatialNodeIndex,
     pub current_target_spatial_node_index: SpatialNodeIndex,
-    pub bounds: TypedRect<f32, T>,
+    pub bounds: Rect<f32, T>,
     visible_face: VisibleFace,
 }
 
 impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
     pub fn new(
         ref_spatial_node_index: SpatialNodeIndex,
-        bounds: TypedRect<f32, T>,
+        bounds: Rect<f32, T>,
     ) -> Self {
         SpaceMapper {
             kind: CoordinateSpaceMapping::Local,
             ref_spatial_node_index,
             current_target_spatial_node_index: ref_spatial_node_index,
             bounds,
             visible_face: VisibleFace::Front,
         }
     }
 
     pub fn new_with_target(
         ref_spatial_node_index: SpatialNodeIndex,
         target_node_index: SpatialNodeIndex,
-        bounds: TypedRect<f32, T>,
+        bounds: Rect<f32, T>,
         clip_scroll_tree: &ClipScrollTree,
     ) -> Self {
         let mut mapper = Self::new(ref_spatial_node_index, bounds);
         mapper.set_target_spatial_node(target_node_index, clip_scroll_tree);
         mapper
     }
 
     pub fn set_target_spatial_node(
@@ -190,48 +190,48 @@ impl<F, T> SpaceMapper<F, T> where F: fm
                 .with_destination::<T>();
             CoordinateSpaceMapping::Transform(transform)
         };
 
         self.visible_face = self.kind.visible_face();
         self.current_target_spatial_node_index = target_node_index;
     }
 
-    pub fn get_transform(&self) -> TypedTransform3D<f32, F, T> {
+    pub fn get_transform(&self) -> Transform3D<f32, F, T> {
         match self.kind {
             CoordinateSpaceMapping::Local => {
-                TypedTransform3D::identity()
+                Transform3D::identity()
             }
             CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
                 scale_offset.to_transform()
             }
             CoordinateSpaceMapping::Transform(transform) => {
                 transform
             }
         }
     }
 
-    pub fn unmap(&self, rect: &TypedRect<f32, T>) -> Option<TypedRect<f32, F>> {
+    pub fn unmap(&self, rect: &Rect<f32, T>) -> Option<Rect<f32, F>> {
         match self.kind {
             CoordinateSpaceMapping::Local => {
-                Some(TypedRect::from_untyped(&rect.to_untyped()))
+                Some(Rect::from_untyped(&rect.to_untyped()))
             }
             CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
                 Some(scale_offset.unmap_rect(rect))
             }
             CoordinateSpaceMapping::Transform(ref transform) => {
                 transform.inverse_rect_footprint(rect)
             }
         }
     }
 
-    pub fn map(&self, rect: &TypedRect<f32, F>) -> Option<TypedRect<f32, T>> {
+    pub fn map(&self, rect: &Rect<f32, F>) -> Option<Rect<f32, T>> {
         match self.kind {
             CoordinateSpaceMapping::Local => {
-                Some(TypedRect::from_untyped(&rect.to_untyped()))
+                Some(Rect::from_untyped(&rect.to_untyped()))
             }
             CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
                 Some(scale_offset.map_rect(rect))
             }
             CoordinateSpaceMapping::Transform(ref transform) => {
                 match project_rect(transform, rect, &self.bounds) {
                     Some(bounds) => {
                         Some(bounds)
@@ -402,29 +402,18 @@ impl From<SideOffsetsKey> for LayoutSide
             key.top,
             key.right,
             key.bottom,
             key.left,
         )
     }
 }
 
-impl From<LayoutSideOffsets> for SideOffsetsKey {
-    fn from(offsets: LayoutSideOffsets) -> SideOffsetsKey {
-        SideOffsetsKey {
-            top: offsets.top,
-            right: offsets.right,
-            bottom: offsets.bottom,
-            left: offsets.left,
-        }
-    }
-}
-
-impl From<SideOffsets2D<f32>> for SideOffsetsKey {
-    fn from(offsets: SideOffsets2D<f32>) -> SideOffsetsKey {
+impl<U> From<SideOffsets2D<f32, U>> for SideOffsetsKey {
+    fn from(offsets: SideOffsets2D<f32, U>) -> SideOffsetsKey {
         SideOffsetsKey {
             top: offsets.top,
             right: offsets.right,
             bottom: offsets.bottom,
             left: offsets.left,
         }
     }
 }
@@ -448,18 +437,18 @@ impl hash::Hash for SizeKey {
 }
 
 impl From<SizeKey> for LayoutSize {
     fn from(key: SizeKey) -> LayoutSize {
         LayoutSize::new(key.w, key.h)
     }
 }
 
-impl<U> From<TypedSize2D<f32, U>> for SizeKey {
-    fn from(size: TypedSize2D<f32, U>) -> SizeKey {
+impl<U> From<Size2D<f32, U>> for SizeKey {
+    fn from(size: Size2D<f32, U>) -> SizeKey {
         SizeKey {
             w: size.width,
             h: size.height,
         }
     }
 }
 
 /// A hashable vec for using as a key during primitive interning.
@@ -1205,17 +1194,17 @@ impl ClipData {
 /// A hashable descriptor for nine-patches, used by image and
 /// gradient borders.
 #[derive(Debug, Clone, PartialEq, Eq, Hash, MallocSizeOf)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct NinePatchDescriptor {
     pub width: i32,
     pub height: i32,
-    pub slice: SideOffsets2D<i32>,
+    pub slice: DeviceIntSideOffsets,
     pub fill: bool,
     pub repeat_horizontal: RepeatMode,
     pub repeat_vertical: RepeatMode,
     pub outset: SideOffsetsKey,
     pub widths: SideOffsetsKey,
 }
 
 impl IsVisible for PrimitiveKeyKind {
@@ -1937,17 +1926,17 @@ impl PrimitiveStore {
 
                     let shadow_rect = match pic.raster_config {
                         Some(ref rc) => match rc.composite_mode {
                             // If we have a drop shadow filter, we also need to include the shadow in
                             // our local rect for the purpose of calculating the size of the picture.
                             PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
                                 let mut rect = LayoutRect::zero();
                                 for shadow in shadows {
-                                    rect = rect.union(&pic.snapped_local_rect.translate(&shadow.offset));
+                                    rect = rect.union(&pic.snapped_local_rect.translate(shadow.offset));
                                 }
 
                                 rect
                             }
                             _ => LayoutRect::zero(),
                         }
                         None => {
                             if let Some(ref rect) = pic_surface_rect {
@@ -2251,17 +2240,17 @@ impl PrimitiveStore {
         //           remove this invalidation here completely.
         if let Some(ref raster_config) = pic.raster_config {
             // Inflate the local bounding rect if required by the filter effect.
             // This inflaction factor is to be applied to the surface itself.
             surface_rect = raster_config.composite_mode.inflate_picture_rect(surface_rect, surface.inflation_factor);
 
             // Layout space for the picture is picture space from the
             // perspective of its child primitives.
-            let pic_local_rect = surface_rect * TypedScale::new(1.0);
+            let pic_local_rect = surface_rect * Scale::new(1.0);
             if pic.snapped_local_rect != pic_local_rect {
                 match raster_config.composite_mode {
                     PictureCompositeMode::Filter(Filter::DropShadows(..)) => {
                         for handle in &pic.extra_gpu_data_handles {
                             frame_state.gpu_cache.invalidate(handle);
                         }
                     }
                     _ => {}
@@ -2783,17 +2772,17 @@ impl PrimitiveStore {
                     println!("\tline decoration key={:?}", line_dec_data.cache_key);
                 }
 
                 // If we have a cache key, it's a wavy / dashed / dotted line. Otherwise, it's
                 // a simple solid line.
                 if let Some(cache_key) = line_dec_data.cache_key.as_ref() {
                     // TODO(gw): Do we ever need / want to support scales for text decorations
                     //           based on the current transform?
-                    let scale_factor = TypedScale::new(1.0) * device_pixel_scale;
+                    let scale_factor = Scale::new(1.0) * device_pixel_scale;
                     let task_size = (LayoutSize::from_au(cache_key.size) * scale_factor).ceil().to_i32();
 
                     // Request a pre-rendered image task.
                     // TODO(gw): This match is a bit untidy, but it should disappear completely
                     //           once the prepare_prims and batching are unified. When that
                     //           happens, we can use the cache handle immediately, and not need
                     //           to temporarily store it in the primitive instance.
                     *cache_handle = Some(frame_state.resource_cache.request_render_task(
@@ -3491,17 +3480,17 @@ impl<'a> GpuDataRequest<'a> {
                         BoxShadowClipMode::Inset => Some(ClipMode::ClipOut),
                     };
 
                     // Push a region into the segment builder where the
                     // box-shadow can have an effect on the result. This
                     // ensures clip-mask tasks get allocated for these
                     // pixel regions, even if no other clips affect them.
                     let prim_shadow_rect = info.prim_shadow_rect.translate(
-                        &LayoutVector2D::new(clip_instance.local_pos.x, clip_instance.local_pos.y),
+                        LayoutVector2D::new(clip_instance.local_pos.x, clip_instance.local_pos.y),
                     );
                     segment_builder.push_mask_region(
                         prim_shadow_rect,
                         prim_shadow_rect.inflate(
                             -0.5 * info.original_alloc_size.width,
                             -0.5 * info.original_alloc_size.height,
                         ),
                         inner_clip_mode,
@@ -3645,17 +3634,17 @@ impl PrimitiveInstance {
                 prim_clip_chain,
                 &mut frame_state.segment_builder,
                 frame_state.clip_store,
                 data_stores,
             ) {
                 frame_state.segment_builder.build(|segment| {
                     segments.push(
                         BrushSegment::new(
-                            segment.rect.translate(&-prim_local_rect.origin.to_vector()),
+                            segment.rect.translate(-prim_local_rect.origin.to_vector()),
                             segment.has_mask,
                             segment.edge_flags,
                             [0.0; 4],
                             BrushFlags::PERSPECTIVE_INTERPOLATION,
                         ),
                     );
                 });
             }
@@ -3815,17 +3804,17 @@ impl PrimitiveInstance {
                     &prim_info.clip_chain,
                     self.spatial_node_index,
                     &frame_context.clip_scroll_tree,
                 );
 
                 let segment_clip_chain = frame_state
                     .clip_store
                     .build_clip_chain_instance(
-                        segment.local_rect.translate(&LayoutVector2D::new(
+                        segment.local_rect.translate(LayoutVector2D::new(
                             self.prim_origin.x,
                             self.prim_origin.y,
                         )),
                         &pic_state.map_local_to_pic,
                         &pic_state.map_pic_to_world,
                         &frame_context.clip_scroll_tree,
                         frame_state.gpu_cache,
                         frame_state.resource_cache,
@@ -3961,22 +3950,22 @@ impl PrimitiveInstance {
 /// Mimics the GLSL mix() function.
 fn mix(x: f32, y: f32, a: f32) -> f32 {
     x * (1.0 - a) + y * a
 }
 
 /// Given a point within a local rectangle, and the device space corners
 /// of a snapped primitive, return the snap offsets.
 fn compute_snap_offset_impl<PixelSpace>(
-    reference_pos: TypedPoint2D<f32, PixelSpace>,
-    reference_rect: TypedRect<f32, PixelSpace>,
+    reference_pos: Point2D<f32, PixelSpace>,
+    reference_rect: Rect<f32, PixelSpace>,
     prim_top_left: DevicePoint,
     prim_bottom_right: DevicePoint,
 ) -> DeviceVector2D {
-    let normalized_snap_pos = TypedPoint2D::<f32, PixelSpace>::new(
+    let normalized_snap_pos = Point2D::<f32, PixelSpace>::new(
         (reference_pos.x - reference_rect.origin.x) / reference_rect.size.width,
         (reference_pos.y - reference_rect.origin.y) / reference_rect.size.height,
     );
 
     let top_left = DeviceVector2D::new(
         (prim_top_left.x + 0.5).floor() - prim_top_left.x,
         (prim_top_left.y + 0.5).floor() - prim_top_left.y,
     );
@@ -3992,31 +3981,31 @@ fn compute_snap_offset_impl<PixelSpace>(
     )
 }
 
 /// Given the snapping offsets for a primitive rectangle, recompute
 /// the snapping offsets to be relative to given local rectangle.
 /// This *must* exactly match the logic in the GLSL
 /// compute_snap_offset function.
 pub fn recompute_snap_offsets<PixelSpace>(
-    local_rect: TypedRect<f32, PixelSpace>,
-    prim_rect: TypedRect<f32, PixelSpace>,
+    local_rect: Rect<f32, PixelSpace>,
+    prim_rect: Rect<f32, PixelSpace>,
     snap_offsets: SnapOffsets,
 ) -> SnapOffsets
 {
     if prim_rect.is_empty() || snap_offsets.is_empty() {
         return SnapOffsets::empty();
     }
 
-    let normalized_top_left = TypedPoint2D::<f32, PixelSpace>::new(
+    let normalized_top_left = Point2D::<f32, PixelSpace>::new(
         (local_rect.origin.x - prim_rect.origin.x) / prim_rect.size.width,
         (local_rect.origin.y - prim_rect.origin.y) / prim_rect.size.height,
     );
 
-    let normalized_bottom_right = TypedPoint2D::<f32, PixelSpace>::new(
+    let normalized_bottom_right = Point2D::<f32, PixelSpace>::new(
         (local_rect.origin.x + local_rect.size.width - prim_rect.origin.x) / prim_rect.size.width,
         (local_rect.origin.y + local_rect.size.height - prim_rect.origin.y) / prim_rect.size.height,
     );
 
     let top_left = DeviceVector2D::new(
         mix(snap_offsets.top_left.x, snap_offsets.bottom_right.x, normalized_top_left.x),
         mix(snap_offsets.top_left.y, snap_offsets.bottom_right.y, normalized_top_left.y),
     );
@@ -4034,36 +4023,36 @@ pub fn recompute_snap_offsets<PixelSpace
 
 /// Retrieve the exact unsnapped device space rectangle for a primitive.
 fn get_unclipped_device_rect(
     prim_rect: PictureRect,
     map_to_raster: &SpaceMapper<PicturePixel, RasterPixel>,
     device_pixel_scale: DevicePixelScale,
 ) -> Option<DeviceRect> {
     let raster_rect = map_to_raster.map(&prim_rect)?;
-    let world_rect = raster_rect * TypedScale::new(1.0);
+    let world_rect = raster_rect * Scale::new(1.0);
     Some(world_rect * device_pixel_scale)
 }
 
 /// Given an unclipped device rect, try to find a minimal device space
 /// rect to allocate a clip mask for, by clipping to the screen. This
 /// function is very similar to get_raster_rects below. It is far from
 /// ideal, and should be refactored as part of the support for setting
 /// scale per-raster-root.
 fn get_clipped_device_rect(
     unclipped: &DeviceRect,
     prim_snap_offsets: SnapOffsets,
     map_to_world: &SpaceMapper<RasterPixel, WorldPixel>,
     prim_bounding_rect: WorldRect,
     device_pixel_scale: DevicePixelScale,
 ) -> Option<(DeviceIntRect, SnapOffsets)> {
     let unclipped_raster_rect = {
-        let world_rect = *unclipped * TypedScale::new(1.0);
+        let world_rect = *unclipped * Scale::new(1.0);
         let raster_rect = world_rect * device_pixel_scale.inv();
-        TypedRect::from_untyped(&raster_rect.to_untyped())
+        Rect::from_untyped(&raster_rect.to_untyped())
     };
 
     let unclipped_world_rect = map_to_world.map(&unclipped_raster_rect)?;
 
     let clipped_world_rect = unclipped_world_rect.intersection(&prim_bounding_rect)?;
 
     let clipped_raster_rect = map_to_world.unmap(&clipped_world_rect)?;
 
@@ -4137,31 +4126,31 @@ pub fn get_raster_rects(
 
     Some((clipped.to_i32(), unclipped))
 }
 
 /// Snap the given rect in raster space if the transform is
 /// axis-aligned. It return the snapped rect transformed back into the
 /// given pixel space, and the snap offsets in device space.
 pub fn get_snapped_rect<PixelSpace>(
-    prim_rect: TypedRect<f32, PixelSpace>,
+    prim_rect: Rect<f32, PixelSpace>,
     map_to_raster: &SpaceMapper<PixelSpace, RasterPixel>,
     device_pixel_scale: DevicePixelScale,
-) -> Option<(TypedRect<f32, PixelSpace>, SnapOffsets)> where PixelSpace: fmt::Debug {
+) -> Option<(Rect<f32, PixelSpace>, SnapOffsets)> where PixelSpace: fmt::Debug {
     let is_axis_aligned = match map_to_raster.kind {
         CoordinateSpaceMapping::Local |
         CoordinateSpaceMapping::ScaleOffset(..) => true,
         CoordinateSpaceMapping::Transform(ref transform) => transform.preserves_2d_axis_alignment(),
     };
 
     if is_axis_aligned {
        let raster_rect = map_to_raster.map(&prim_rect)?;
 
        let device_rect = {
-            let world_rect = raster_rect * TypedScale::new(1.0);
+            let world_rect = raster_rect * Scale::new(1.0);
             world_rect * device_pixel_scale
         };
 
         let top_left = compute_snap_offset_impl(
             prim_rect.origin,
             prim_rect,
             device_rect.origin,
             device_rect.bottom_right(),
@@ -4180,17 +4169,17 @@ pub fn get_snapped_rect<PixelSpace>(
         };
 
         let snapped_device_rect = DeviceRect::new(
             device_rect.origin + top_left,
             device_rect.size + (bottom_right - top_left).to_size()
         );
 
         let snapped_world_rect = snapped_device_rect / device_pixel_scale;
-        let snapped_raster_rect = snapped_world_rect * TypedScale::new(1.0);
+        let snapped_raster_rect = snapped_world_rect * Scale::new(1.0);
         let snapped_prim_rect = map_to_raster.unmap(&snapped_raster_rect)?;
         Some((snapped_prim_rect, snap_offsets))
     } else {
         None
     }
 }
 
 /// Get the inline (horizontal) and block (vertical) sizes
--- a/gfx/wr/webrender/src/prim_store/text_run.rs
+++ b/gfx/wr/webrender/src/prim_store/text_run.rs
@@ -318,17 +318,17 @@ impl TextRunPrimitive {
 
         if self.glyph_keys_range.is_empty() || cache_dirty {
             let subpx_dir = self.used_font.get_subpx_dir();
 
             self.glyph_keys_range = scratch.glyph_keys.extend(
                 glyphs.iter().map(|src| {
                     let src_point = src.point + prim_offset;
                     let world_offset = self.used_font.transform.transform(&src_point);
-                    let device_offset = device_pixel_scale.transform_point(&world_offset);
+                    let device_offset = device_pixel_scale.transform_point(world_offset);
                     GlyphKey::new(src.index, device_offset, subpx_dir)
                 }));
         }
 
         resource_cache.request_glyphs(
             self.used_font.clone(),
             &scratch.glyph_keys[self.glyph_keys_range],
             gpu_cache,
--- a/gfx/wr/webrender/src/profiler.rs
+++ b/gfx/wr/webrender/src/profiler.rs
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{ColorF, ColorU};
 use crate::debug_render::DebugRenderer;
 use crate::device::query::{GpuSampler, GpuTimer, NamedTag};
-use euclid::{Point2D, Rect, Size2D, vec2};
+use euclid::{Point2D, Rect, Size2D, vec2, default};
 use crate::internal_types::FastHashMap;
 use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, wr_has_been_initialized};
 use std::collections::vec_deque::VecDeque;
 use std::{f32, mem};
 use std::ffi::CStr;
 use std::time::Duration;
 use time::precise_time_ns;
 
@@ -682,17 +682,17 @@ impl ProfileGraph {
     }
 
     fn draw_graph(
         &self,
         x: f32,
         y: f32,
         description: &'static str,
         debug_renderer: &mut DebugRenderer,
-    ) -> Rect<f32> {
+    ) -> default::Rect<f32> {
         let size = Size2D::new(600.0, 120.0);
         let line_height = debug_renderer.line_height();
         let graph_rect = Rect::new(Point2D::new(x, y), size);
         let mut rect = graph_rect.inflate(10.0, 10.0);
 
         let stats = self.stats();
 
         let text_color = ColorU::new(255, 255, 0, 255);
@@ -807,17 +807,17 @@ impl GpuFrameCollection {
         self.frames.push_front(GpuFrame {
             total_time,
             samples,
         });
     }
 }
 
 impl GpuFrameCollection {
-    fn draw(&self, x: f32, y: f32, debug_renderer: &mut DebugRenderer) -> Rect<f32> {
+    fn draw(&self, x: f32, y: f32, debug_renderer: &mut DebugRenderer) -> default::Rect<f32> {
         let graph_rect = Rect::new(
             Point2D::new(x, y),
             Size2D::new(GRAPH_WIDTH, GRAPH_HEIGHT),
         );
         let bounding_rect = graph_rect.inflate(GRAPH_PADDING, GRAPH_PADDING);
 
         debug_renderer.add_quad(
             bounding_rect.origin.x,
@@ -1014,17 +1014,17 @@ impl Profiler {
     }
 
     fn draw_bar(
         &mut self,
         label: &str,
         label_color: ColorU,
         counters: &[(ColorU, &IntProfileCounter)],
         debug_renderer: &mut DebugRenderer,
-    ) -> Rect<f32> {
+    ) -> default::Rect<f32> {
         let mut rect = debug_renderer.add_text(
             self.draw_state.x_left,
             self.draw_state.y_left,
             label,
             label_color,
             None,
         );
 
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -1718,18 +1718,18 @@ impl RenderTask {
             }
             #[cfg(test)]
             RenderTaskKind::Test(..) => {
                 panic!("RenderTask tests aren't expected to exercise this code");
             }
         };
 
         if let Some(mut request) = gpu_cache.request(cache_handle) {
-            let p0 = target_rect.origin.to_f32();
-            let p1 = target_rect.bottom_right().to_f32();
+            let p0 = target_rect.min().to_f32();
+            let p1 = target_rect.max().to_f32();
             let image_source = ImageSource {
                 p0,
                 p1,
                 texture_layer: target_index.0 as f32,
                 user_data: [0.0; 3],
                 uv_rect_kind,
             };
             image_source.write_gpu_blocks(&mut request);
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -50,17 +50,17 @@ use crate::capture::{CaptureConfig, Exte
 use crate::debug_colors;
 use crate::debug_render::{DebugItem, DebugRenderer};
 use crate::device::{DepthFunction, Device, GpuFrameId, Program, UploadMethod, Texture, PBO};
 use crate::device::{DrawTarget, ExternalTexture, FBOId, ReadTarget, TextureSlot};
 use crate::device::{ShaderError, TextureFilter, TextureFlags,
              VertexUsageHint, VAO, VBO, CustomVAO};
 use crate::device::{ProgramCache};
 use crate::device::query::GpuTimer;
-use euclid::{rect, Transform3D, TypedScale};
+use euclid::{rect, Transform3D, Scale, default};
 use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig};
 use gleam::gl;
 use crate::glyph_cache::GlyphCache;
 use crate::glyph_rasterizer::{GlyphFormat, GlyphRasterizer};
 use crate::gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList};
 use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
 use crate::gpu_types::{PrimitiveHeaderI, PrimitiveHeaderF, ScalingInstance, SvgFilterInstance, TransformData, ResolveInstanceData};
 use crate::internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
@@ -3316,17 +3316,17 @@ impl Renderer {
             false,
         );
 
         let mut src = DeviceIntRect::new(
             source_screen_origin + (backdrop_rect.origin - backdrop_screen_origin),
             readback_rect.size,
         );
         let mut dest = readback_rect.to_i32();
-        let device_to_framebuffer = TypedScale::new(1i32);
+        let device_to_framebuffer = Scale::new(1i32);
 
         // Need to invert the y coordinates and flip the image vertically when
         // reading back from the framebuffer.
         if draw_target.is_default() {
             src.origin.y = draw_target.dimensions().height as i32 - src.size.height - src.origin.y;
             dest.origin.y += dest.size.height;
             dest.size.height = -dest.size.height;
         }
@@ -3392,27 +3392,27 @@ impl Renderer {
                 layer,
                 false,
             );
 
             device.blit_render_target(
                 read_target.into(),
                 read_target.to_framebuffer_rect(source_rect),
                 draw_target,
-                draw_target.to_framebuffer_rect(blit.target_rect.translate(&-content_origin.to_vector())),
+                draw_target.to_framebuffer_rect(blit.target_rect.translate(-content_origin.to_vector())),
                 TextureFilter::Linear,
             );
         }
     }
 
     fn handle_scaling(
         &mut self,
         scalings: &[ScalingInstance],
         source: TextureSource,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         stats: &mut RendererStats,
     ) {
         if scalings.is_empty() {
             return
         }
 
         let _timer = self.gpu_profile.start_timer(GPU_TAG_SCALE);
 
@@ -3432,17 +3432,17 @@ impl Renderer {
             stats,
         );
     }
 
     fn handle_svg_filters(
         &mut self,
         textures: &BatchTextures,
         svg_filters: &[SvgFilterInstance],
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         stats: &mut RendererStats,
     ) {
         if svg_filters.is_empty() {
             return;
         }
 
         let _timer = self.gpu_profile.start_timer(GPU_TAG_SVG_FILTER);
 
@@ -3460,17 +3460,17 @@ impl Renderer {
         );
     }
 
     fn draw_picture_cache_target(
         &mut self,
         target: &PictureCacheTarget,
         draw_target: DrawTarget,
         content_origin: DeviceIntPoint,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         render_tasks: &RenderTaskGraph,
         stats: &mut RendererStats,
     ) {
         self.profile_counters.color_targets.inc();
         let _gm = self.gpu_profile.start_marker("picture cache target");
         let framebuffer_kind = FramebufferKind::Other;
 
         {
@@ -3503,17 +3503,17 @@ impl Renderer {
     /// Draw an alpha batch container into a given draw target. This is used
     /// by both color and picture cache target kinds.
     fn draw_alpha_batch_container(
         &mut self,
         alpha_batch_container: &AlphaBatchContainer,
         draw_target: DrawTarget,
         content_origin: DeviceIntPoint,
         framebuffer_kind: FramebufferKind,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         render_tasks: &RenderTaskGraph,
         stats: &mut RendererStats,
     ) {
         let uses_scissor = alpha_batch_container.task_scissor_rect.is_some();
 
         if uses_scissor {
             self.device.enable_scissor();
             let scissor_rect = draw_target.build_scissor_rect(
@@ -3713,17 +3713,17 @@ impl Renderer {
     fn draw_color_target(
         &mut self,
         draw_target: DrawTarget,
         target: &ColorRenderTarget,
         content_origin: DeviceIntPoint,
         clear_color: Option<[f32; 4]>,
         clear_depth: Option<f32>,
         render_tasks: &RenderTaskGraph,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         frame_id: GpuFrameId,
         stats: &mut RendererStats,
     ) {
         self.profile_counters.color_targets.inc();
         let _gm = self.gpu_profile.start_marker("color target");
 
         // sanity check for the depth buffer
         if let DrawTarget::Texture { with_depth, .. } = draw_target {
@@ -3869,30 +3869,30 @@ impl Renderer {
                         let target = entry.get_mut();
                         target.last_access = frame_id;
                         target.fbo_id
                     }
                 };
                 let (src_rect, _) = render_tasks[output.task_id].get_target_rect();
                 self.device.blit_render_target_invert_y(
                     draw_target.into(),
-                    draw_target.to_framebuffer_rect(src_rect.translate(&-content_origin.to_vector())),
+                    draw_target.to_framebuffer_rect(src_rect.translate(-content_origin.to_vector())),
                     DrawTarget::External { fbo: fbo_id, size: output_size },
                     output_size.into(),
                 );
                 handler.unlock(output.pipeline_id);
             }
         }
     }
 
     /// Draw all the instances in a clip batcher list to the current target.
     fn draw_clip_batch_list(
         &mut self,
         list: &ClipBatchList,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         stats: &mut RendererStats,
     ) {
         if self.debug_flags.contains(DebugFlags::DISABLE_CLIP_MASKS) {
             return;
         }
 
         // draw rounded cornered rectangles
         if !list.slow_rectangles.is_empty() {
@@ -3963,17 +3963,17 @@ impl Renderer {
             );
         }
     }
 
     fn draw_alpha_target(
         &mut self,
         draw_target: DrawTarget,
         target: &AlphaRenderTarget,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         render_tasks: &RenderTaskGraph,
         stats: &mut RendererStats,
     ) {
         self.profile_counters.alpha_targets.inc();
         let _gm = self.gpu_profile.start_marker("alpha target");
         let alpha_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_ALPHA);
 
         {
@@ -4503,17 +4503,17 @@ impl Renderer {
                             offset.x,
                             offset.x + size.width,
                             offset.y + size.height,
                             offset.y,
                             ORTHO_NEAR_PLANE,
                             ORTHO_FAR_PLANE,
                         );
 
-                        let fb_scale = TypedScale::<_, _, FramebufferPixel>::new(1i32);
+                        let fb_scale = Scale::<_, _, FramebufferPixel>::new(1i32);
                         let mut fb_rect = frame.device_rect * fb_scale;
                         fb_rect.origin.y = device_size.height - fb_rect.origin.y - fb_rect.size.height;
 
                         let draw_target = DrawTarget::Default {
                             rect: fb_rect,
                             total_size: device_size * fb_scale,
                         };
                         if clear_framebuffer {
@@ -4690,17 +4690,17 @@ impl Renderer {
 
         frame.has_been_rendered = true;
     }
 
     /// Initialize the PLS block, by reading the current framebuffer color.
     pub fn init_pixel_local_storage(
         &mut self,
         task_rect: DeviceIntRect,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         stats: &mut RendererStats,
     ) {
         self.device.enable_pixel_local_storage(true);
 
         self.shaders
             .borrow_mut()
             .pls_init
             .bind(
@@ -4720,17 +4720,17 @@ impl Renderer {
             stats,
         );
     }
 
     /// Resolve the current PLS structure, writing it to a fragment color output.
     pub fn resolve_pixel_local_storage(
         &mut self,
         task_rect: DeviceIntRect,
-        projection: &Transform3D<f32>,
+        projection: &default::Transform3D<f32>,
         stats: &mut RendererStats,
     ) {
         self.shaders
             .borrow_mut()
             .pls_resolve
             .bind(
                 &mut self.device,
                 projection,
@@ -4883,17 +4883,17 @@ impl Renderer {
                 device_size.width - target_size.width - 64,
                 device_size.height - target_size.height - 64,
             ),
             target_size,
         );
 
         let texture_rect = FramebufferIntRect::new(
             FramebufferIntPoint::zero(),
-            FramebufferIntSize::from_untyped(&source_rect.size.to_untyped()),
+            FramebufferIntSize::from_untyped(source_rect.size.to_untyped()),
         );
 
         debug_renderer.add_rect(
             &target_rect.inflate(1, 1),
             debug_colors::RED.into(),
         );
 
         if self.zoom_debug_texture.is_none() {
@@ -5140,17 +5140,17 @@ impl Renderer {
     pub fn read_pixels_rgba8(&mut self, rect: FramebufferIntRect) -> Vec<u8> {
         let mut pixels = vec![0; (rect.size.width * rect.size.height * 4) as usize];
         self.device.read_pixels_into(rect, ImageFormat::RGBA8, &mut pixels);
         pixels
     }
 
     pub fn read_gpu_cache(&mut self) -> (DeviceIntSize, Vec<u8>) {
         let texture = self.gpu_cache_texture.texture.as_ref().unwrap();
-        let size = FramebufferIntSize::from_untyped(&texture.get_dimensions().to_untyped());
+        let size = FramebufferIntSize::from_untyped(texture.get_dimensions().to_untyped());
         let mut texels = vec![0; (size.width * size.height * 16) as usize];
         self.device.begin_frame();
         self.device.bind_read_target(ReadTarget::from_texture(texture, 0));
         self.device.read_pixels_into(
             size.into(),
             ImageFormat::RGBAF32,
             &mut texels,
         );
@@ -5661,17 +5661,17 @@ impl Renderer {
             .expect(&format!("Unable to create {}", short_path));
         let bytes_per_layer = (rect_size.width * rect_size.height * bytes_per_pixel) as usize;
         let mut data = vec![0; bytes_per_layer];
 
         //TODO: instead of reading from an FBO with `read_pixels*`, we could
         // read from textures directly with `get_tex_image*`.
 
         for layer_id in 0 .. texture.get_layer_count() {
-            let rect = FramebufferIntSize::from_untyped(&rect_size.to_untyped()).into();
+            let rect = FramebufferIntSize::from_untyped(rect_size.to_untyped()).into();
 
             device.attach_read_texture(texture, layer_id);
             #[cfg(feature = "png")]
             {
                 let mut png_data;
                 let (data_ref, format) = match texture.get_format() {
                     ImageFormat::RGBAF32 => {
                         png_data = vec![0; (rect_size.width * rect_size.height * 4) as usize];
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -713,26 +713,26 @@ impl ResourceCache {
         // It happens when originally requested tile range exceeds MAX_TILES_PER_REQUEST.
         for req in supp.clear_requests {
             let tiles = match self.rasterized_blob_images.get_mut(&req.key) {
                 Some(RasterizedBlob::Tiled(tiles)) => tiles,
                 _ => { continue; }
             };
 
             tiles.retain(|tile, _| {
-                !req.original_tile_range.contains(tile) ||
-                req.actual_tile_range.contains(tile)
+                !req.original_tile_range.contains(*tile) ||
+                req.actual_tile_range.contains(*tile)
             });
 
             let texture_cache = &mut self.texture_cache;
             match self.cached_images.try_get_mut(&req.key.as_image()) {
                 Some(&mut ImageResult::Multi(ref mut entries)) => {
                     entries.retain(|key, entry| {
-                        if !req.original_tile_range.contains(&key.tile.unwrap()) ||
-                           req.actual_tile_range.contains(&key.tile.unwrap()) {
+                        if !req.original_tile_range.contains(key.tile.unwrap()) ||
+                           req.actual_tile_range.contains(key.tile.unwrap()) {
                             return true;
                         }
                         entry.mark_unused(texture_cache);
                         return false;
                     });
                 }
                 _ => {}
             }
@@ -1381,23 +1381,23 @@ impl ResourceCache {
             _ => { return; }
         };
 
         let tile_range = compute_tile_range(
             &area,
             tile_size,
         );
 
-        tiles.retain(|tile, _| { tile_range.contains(tile) });
+        tiles.retain(|tile, _| { tile_range.contains(*tile) });
 
         let texture_cache = &mut self.texture_cache;
         match self.cached_images.try_get_mut(&key.as_image()) {
             Some(&mut ImageResult::Multi(ref mut entries)) => {
                 entries.retain(|key, entry| {
-                    if key.tile.is_none() || tile_range.contains(&key.tile.unwrap()) {
+                    if key.tile.is_none() || tile_range.contains(key.tile.unwrap()) {
                         return true;
                     }
                     entry.mark_unused(texture_cache);
                     return false;
                 });
             }
             _ => {}
         }
--- a/gfx/wr/webrender/src/shade.rs
+++ b/gfx/wr/webrender/src/shade.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use crate::batch::{BatchKey, BatchKind, BrushBatchKind, BatchFeatures};
 use crate::device::{Device, Program, ShaderError};
-use euclid::{Transform3D};
+use euclid::default::Transform3D;
 use crate::glyph_rasterizer::GlyphFormat;
 use crate::renderer::{
     desc,
     MAX_VERTEX_TEXTURE_WIDTH,
     BlendMode, DebugFlags, ImageBufferKind, RendererError, RendererOptions,
     TextureSampler, VertexArrayKind, ShaderPrecacheFlags,
 };
 
--- a/gfx/wr/webrender/src/spatial_node.rs
+++ b/gfx/wr/webrender/src/spatial_node.rs
@@ -304,33 +304,33 @@ impl SpatialNode {
                                 self.parent,
                                 external_id,
                                 previous_spatial_nodes,
                             );
 
                             // Do a change-basis operation on the
                             // perspective matrix using the scroll offset.
                             source_transform
-                                .pre_translate(&scroll_offset)
-                                .post_translate(&-scroll_offset)
+                                .pre_translate(scroll_offset)
+                                .post_translate(-scroll_offset)
                         }
                         ReferenceFrameKind::Perspective { scrolling_relative_to: None } |
                         ReferenceFrameKind::Transform => source_transform,
                     };
 
                     let resolved_transform =
                         LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
-                            .pre_mul(&source_transform);
+                            .pre_transform(&source_transform);
 
                     // The transformation for this viewport in world coordinates is the transformation for
                     // our parent reference frame, plus any accumulated scrolling offsets from nodes
                     // between our reference frame and this node. Finally, we also include
                     // whatever local transformation this reference frame provides.
                     let relative_transform = resolved_transform
-                        .post_translate(&state.parent_accumulated_scroll_offset)
+                        .post_translate(state.parent_accumulated_scroll_offset)
                         .to_transform()
                         .with_destination::<LayoutPixel>();
 
                     let mut reset_cs_id = match info.transform_style {
                         TransformStyle::Preserve3D => !state.preserves_3d,
                         TransformStyle::Flat => state.preserves_3d,
                     };
 
@@ -347,26 +347,26 @@ impl SpatialNode {
                             None => reset_cs_id = true,
                         }
                     }
                     if reset_cs_id {
                         // If we break 2D axis alignment or have a perspective component, we need to start a
                         // new incompatible coordinate system with which we cannot share clips without masking.
                         let transform = state.coordinate_system_relative_scale_offset
                             .to_transform()
-                            .pre_mul(&relative_transform);
+                            .pre_transform(&relative_transform);
 
                         // Push that new coordinate system and record the new id.
                         let coord_system = {
                             let parent_system = &coord_systems[state.current_coordinate_system_id.0 as usize];
                             let mut cur_transform = transform;
                             if parent_system.should_flatten {
                                 cur_transform.flatten_z_output();
                             }
-                            let world_transform = cur_transform.post_mul(&parent_system.world_transform);
+                            let world_transform = cur_transform.post_transform(&parent_system.world_transform);
                             let determinant = world_transform.determinant();
                             info.invertible = determinant != 0.0 && !determinant.is_nan();
 
                             CoordinateSystem {
                                 transform,
                                 world_transform,
                                 should_flatten: match (info.transform_style, info.kind) {
                                     (TransformStyle::Flat, ReferenceFrameKind::Transform) => true,
@@ -432,17 +432,17 @@ impl SpatialNode {
             return LayoutVector2D::zero();
         }
 
         // The viewport and margins of the item establishes the maximum amount that it can
         // be offset in order to keep it on screen. Since we care about the relationship
         // between the scrolled content and unscrolled viewport we adjust the viewport's
         // position by the scroll offset in order to work with their relative positions on the
         // page.
-        let sticky_rect = info.frame_rect.translate(viewport_scroll_offset);
+        let sticky_rect = info.frame_rect.translate(*viewport_scroll_offset);
 
         let mut sticky_offset = LayoutVector2D::zero();
         if let Some(margin) = info.margins.top {
             let top_viewport_edge = viewport_rect.min_y() + margin;
             if sticky_rect.min_y() < top_viewport_edge {
                 // If the sticky rect is positioned above the top edge of the viewport (plus margin)
                 // we move it down so that it is fully inside the viewport.
                 sticky_offset.y = top_viewport_edge - sticky_rect.min_y();
@@ -555,17 +555,17 @@ impl SpatialNode {
             }
             SpatialNodeType::ReferenceFrame(ref info) => {
                 state.preserves_3d = info.transform_style == TransformStyle::Preserve3D;
                 state.parent_accumulated_scroll_offset = LayoutVector2D::zero();
                 state.coordinate_system_relative_scale_offset = self.content_transform;
                 let translation = -info.origin_in_parent_reference_frame;
                 state.nearest_scrolling_ancestor_viewport =
                     state.nearest_scrolling_ancestor_viewport
-                       .translate(&translation);
+                       .translate(translation);
             }
         }
     }
 
     pub fn scroll(&mut self, scroll_location: ScrollLocation) -> bool {
         // TODO(gw): This scroll method doesn't currently support
         //           scroll nodes with non-zero external scroll
         //           offsets. However, it's never used by Gecko,
@@ -758,27 +758,27 @@ pub struct ReferenceFrameInfo {
 
     /// True if the resolved transform is invertible.
     pub invertible: bool,
 }
 
 #[derive(Clone, Debug)]
 pub struct StickyFrameInfo {
     pub frame_rect: LayoutRect,
-    pub margins: SideOffsets2D<Option<f32>>,
+    pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
     pub vertical_offset_bounds: StickyOffsetBounds,
     pub horizontal_offset_bounds: StickyOffsetBounds,
     pub previously_applied_offset: LayoutVector2D,
     pub current_offset: LayoutVector2D,
 }
 
 impl StickyFrameInfo {
     pub fn new(
         frame_rect: LayoutRect,
-        margins: SideOffsets2D<Option<f32>>,
+        margins: SideOffsets2D<Option<f32>, LayoutPixel>,
         vertical_offset_bounds: StickyOffsetBounds,
         horizontal_offset_bounds: StickyOffsetBounds,
         previously_applied_offset: LayoutVector2D
     ) -> StickyFrameInfo {
         StickyFrameInfo {
             frame_rect,
             margins,
             vertical_offset_bounds,
--- a/gfx/wr/webrender/src/util.rs
+++ b/gfx/wr/webrender/src/util.rs
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::BorderRadius;
 use api::units::*;
-use euclid::{TypedPoint2D, TypedRect, TypedSize2D, Vector2D};
-use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D, TypedScale};
+use euclid::{Point2D, Rect, Size2D, Vector2D};
+use euclid::{default, Transform2D, Transform3D, Scale};
 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
 use plane_split::{Clipper, Polygon};
 use std::{i32, f32, fmt, ptr};
 use std::borrow::Cow;
 use std::os::raw::c_void;
 use std::sync::Arc;
 use std::mem::replace;
 
@@ -114,32 +114,32 @@ impl<T> VecHelper<T> for Vec<T> {
 // an axis align rectangle under transformation). The
 // scaling is applied first, followed by the translation.
 // TODO(gw): We should try and incorporate F <-> T units here,
 //           but it's a bit tricky to do that now with the
 //           way the current clip-scroll tree works.
 #[derive(Debug, Clone, Copy, MallocSizeOf)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 pub struct ScaleOffset {
-    pub scale: Vector2D<f32>,
-    pub offset: Vector2D<f32>,
+    pub scale: default::Vector2D<f32>,
+    pub offset: default::Vector2D<f32>,
 }
 
 impl ScaleOffset {
     pub fn identity() -> Self {
         ScaleOffset {
             scale: Vector2D::new(1.0, 1.0),
             offset: Vector2D::zero(),
         }
     }
 
     // Construct a ScaleOffset from a transform. Returns
     // None if the matrix is not a pure scale / translation.
     pub fn from_transform<F, T>(
-        m: &TypedTransform3D<f32, F, T>,
+        m: &Transform3D<f32, F, T>,
     ) -> Option<ScaleOffset> {
 
         // To check that we have a pure scale / translation:
         // Every field must match an identity matrix, except:
         //  - Any value present in tx,ty
         //  - Any non-neg value present in sx,sy (avoid negative for reflection/rotation)
 
         if m.m11 < 0.0 ||
@@ -173,69 +173,69 @@ impl ScaleOffset {
             ),
             offset: Vector2D::new(
                 -self.offset.x / self.scale.x,
                 -self.offset.y / self.scale.y,
             ),
         }
     }
 
-    pub fn offset(&self, offset: Vector2D<f32>) -> Self {
+    pub fn offset(&self, offset: default::Vector2D<f32>) -> Self {
         self.accumulate(
             &ScaleOffset {
                 scale: Vector2D::new(1.0, 1.0),
                 offset,
             }
         )
     }
 
     /// Produce a ScaleOffset that includes both self and other.
     /// The 'self' ScaleOffset is applied after other.
-    /// This is equivalent to `TypedTransform3D::pre_mul`.
+    /// This is equivalent to `Transform3D::pre_transform`.
     pub fn accumulate(&self, other: &ScaleOffset) -> Self {
         ScaleOffset {
             scale: Vector2D::new(
                 self.scale.x * other.scale.x,
                 self.scale.y * other.scale.y,
             ),
             offset: Vector2D::new(
                 self.offset.x + self.scale.x * other.offset.x,
                 self.offset.y + self.scale.y * other.offset.y,
             ),
         }
     }
 
-    pub fn map_rect<F, T>(&self, rect: &TypedRect<f32, F>) -> TypedRect<f32, T> {
-        TypedRect::new(
-            TypedPoint2D::new(
+    pub fn map_rect<F, T>(&self, rect: &Rect<f32, F>) -> Rect<f32, T> {
+        Rect::new(
+            Point2D::new(
                 rect.origin.x * self.scale.x + self.offset.x,
                 rect.origin.y * self.scale.y + self.offset.y,
             ),
-            TypedSize2D::new(
+            Size2D::new(
                 rect.size.width * self.scale.x,
                 rect.size.height * self.scale.y,
             )
         )
     }
 
-    pub fn unmap_rect<F, T>(&self, rect: &TypedRect<f32, F>) -> TypedRect<f32, T> {
-        TypedRect::new(
-            TypedPoint2D::new(
+    pub fn unmap_rect<F, T>(&self, rect: &Rect<f32, F>) -> Rect<f32, T> {
+        Rect::new(
+            Point2D::new(
                 (rect.origin.x - self.offset.x) / self.scale.x,
                 (rect.origin.y - self.offset.y) / self.scale.y,
             ),
-            TypedSize2D::new(
+            Size2D::new(
                 rect.size.width / self.scale.x,
                 rect.size.height / self.scale.y,
             )
         )
     }
 
-    pub fn to_transform<F, T>(&self) -> TypedTransform3D<f32, F, T> {
-        TypedTransform3D::row_major(
+    pub fn to_transform<F, T>(&self) -> Transform3D<f32, F, T> {
+        Transform3D::row_major(
             self.scale.x,
             0.0,
             0.0,
             0.0,
 
             0.0,
             self.scale.y,
             0.0,
@@ -259,33 +259,33 @@ pub trait MatrixHelpers<Src, Dst> {
     /// A port of the preserves2dAxisAlignment function in Skia.
     /// Defined in the SkMatrix44 class.
     fn preserves_2d_axis_alignment(&self) -> bool;
     fn has_perspective_component(&self) -> bool;
     fn has_2d_inverse(&self) -> bool;
     /// Check if the matrix post-scaling on either the X or Y axes could cause geometry
     /// transformed by this matrix to have scaling exceeding the supplied limit.
     fn exceeds_2d_scale(&self, limit: f64) -> bool;
-    fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>>;
-    fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>>;
+    fn inverse_project(&self, target: &Point2D<f32, Dst>) -> Option<Point2D<f32, Src>>;
+    fn inverse_rect_footprint(&self, rect: &Rect<f32, Dst>) -> Option<Rect<f32, Src>>;
     fn transform_kind(&self) -> TransformedRectKind;
     fn is_simple_translation(&self) -> bool;
     fn is_simple_2d_translation(&self) -> bool;
     /// Return the determinant of the 2D part of the matrix.
     fn determinant_2d(&self) -> f32;
     /// This function returns a point in the `Src` space that projects into zero XY.
     /// It ignores the Z coordinate and is usable for "flattened" transformations,
     /// since they are not generally inversible.
-    fn inverse_project_2d_origin(&self) -> Option<TypedPoint2D<f32, Src>>;
+    fn inverse_project_2d_origin(&self) -> Option<Point2D<f32, Src>>;
     /// Turn Z transformation into identity. This is useful when crossing "flat"
     /// transform styled stacking contexts upon traversing the coordinate systems.
     fn flatten_z_output(&mut self);
 }
 
-impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
+impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
     fn preserves_2d_axis_alignment(&self) -> bool {
         if self.m14 != 0.0 || self.m24 != 0.0 {
             return false;
         }
 
         let mut col0 = 0;
         let mut col1 = 0;
         let mut row0 = 0;
@@ -323,31 +323,31 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> f
     }
 
     fn exceeds_2d_scale(&self, limit: f64) -> bool {
         let limit2 = (limit * limit) as f32;
         self.m11 * self.m11 + self.m12 * self.m12 > limit2 ||
         self.m21 * self.m21 + self.m22 * self.m22 > limit2
     }
 
-    fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>> {
-        let m: TypedTransform2D<f32, Src, Dst>;
-        m = TypedTransform2D::column_major(
+    fn inverse_project(&self, target: &Point2D<f32, Dst>) -> Option<Point2D<f32, Src>> {
+        let m: Transform2D<f32, Src, Dst>;
+        m = Transform2D::column_major(
             self.m11 - target.x * self.m14,
             self.m21 - target.x * self.m24,
             self.m41 - target.x * self.m44,
             self.m12 - target.y * self.m14,
             self.m22 - target.y * self.m24,
             self.m42 - target.y * self.m44,
         );
-        m.inverse().map(|inv| TypedPoint2D::new(inv.m31, inv.m32))
+        m.inverse().map(|inv| Point2D::new(inv.m31, inv.m32))
     }
 
-    fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>> {
-        Some(TypedRect::from_points(&[
+    fn inverse_rect_footprint(&self, rect: &Rect<f32, Dst>) -> Option<Rect<f32, Src>> {
+        Some(Rect::from_points(&[
             self.inverse_project(&rect.origin)?,
             self.inverse_project(&rect.top_right())?,
             self.inverse_project(&rect.bottom_left())?,
             self.inverse_project(&rect.bottom_right())?,
         ]))
     }
 
     fn transform_kind(&self) -> TransformedRectKind {
@@ -380,22 +380,22 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> f
 
         self.m43.abs() < NEARLY_ZERO
     }
 
     fn determinant_2d(&self) -> f32 {
         self.m11 * self.m22 - self.m12 * self.m21
     }
 
-    fn inverse_project_2d_origin(&self) -> Option<TypedPoint2D<f32, Src>> {
+    fn inverse_project_2d_origin(&self) -> Option<Point2D<f32, Src>> {
         let det = self.determinant_2d();
         if det != 0.0 {
             let x = (self.m21 * self.m42 - self.m41 * self.m22) / det;
             let y = (self.m12 * self.m41 - self.m11 * self.m42) / det;
-            Some(TypedPoint2D::new(x, y))
+            Some(Point2D::new(x, y))
         } else {
             None
         }
     }
 
     fn flatten_z_output(&mut self) {
         self.m13 = 0.0;
         self.m23 = 0.0;
@@ -407,21 +407,21 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> f
 pub trait RectHelpers<U>
 where
     Self: Sized,
 {
     fn from_floats(x0: f32, y0: f32, x1: f32, y1: f32) -> Self;
     fn is_well_formed_and_nonempty(&self) -> bool;
 }
 
-impl<U> RectHelpers<U> for TypedRect<f32, U> {
+impl<U> RectHelpers<U> for Rect<f32, U> {
     fn from_floats(x0: f32, y0: f32, x1: f32, y1: f32) -> Self {
-        TypedRect::new(
-            TypedPoint2D::new(x0, y0),
-            TypedSize2D::new(x1 - x0, y1 - y0),
+        Rect::new(
+            Point2D::new(x0, y0),
+            Size2D::new(x1 - x0, y1 - y0),
         )
     }
 
     fn is_well_formed_and_nonempty(&self) -> bool {
         self.size.width > 0.0 && self.size.height > 0.0
     }
 }
 
@@ -440,55 +440,56 @@ pub enum TransformedRectKind {
 
 #[inline(always)]
 pub fn pack_as_float(value: u32) -> f32 {
     value as f32 + 0.5
 }
 
 #[inline]
 fn extract_inner_rect_impl<U>(
-    rect: &TypedRect<f32, U>,
+    rect: &Rect<f32, U>,
     radii: &BorderRadius,
     k: f32,
-) -> Option<TypedRect<f32, U>> {
+) -> Option<Rect<f32, U>> {
     // `k` defines how much border is taken into account
     // We enforce the offsets to be rounded to pixel boundaries
     // by `ceil`-ing and `floor`-ing them
 
     let xl = (k * radii.top_left.width.max(radii.bottom_left.width)).ceil();
     let xr = (rect.size.width - k * radii.top_right.width.max(radii.bottom_right.width)).floor();
     let yt = (k * radii.top_left.height.max(radii.top_right.height)).ceil();
     let yb =
         (rect.size.height - k * radii.bottom_left.height.max(radii.bottom_right.height)).floor();
 
     if xl <= xr && yt <= yb {
-        Some(TypedRect::new(
-            TypedPoint2D::new(rect.origin.x + xl, rect.origin.y + yt),
-            TypedSize2D::new(xr - xl, yb - yt),
+        Some(Rect::new(
+            Point2D::new(rect.origin.x + xl, rect.origin.y + yt),
+            Size2D::new(xr - xl, yb - yt),
         ))
     } else {
         None
     }
 }
 
 /// Return an aligned rectangle that is inside the clip region and doesn't intersect
 /// any of the bounding rectangles of the rounded corners.
 pub fn extract_inner_rect_safe<U>(
-    rect: &TypedRect<f32, U>,
+    rect: &Rect<f32, U>,
     radii: &BorderRadius,
-) -> Option<TypedRect<f32, U>> {
+) -> Option<Rect<f32, U>> {
     // value of `k==1.0` is used for extraction of the corner rectangles
     // see `SEGMENT_CORNER_*` in `clip_shared.glsl`
     extract_inner_rect_impl(rect, radii, 1.0)
 }
 
 #[cfg(test)]
 pub mod test {
     use super::*;
-    use euclid::{Point2D, Angle, Transform3D};
+    use euclid::default::{Point2D, Transform3D};
+    use euclid::Angle;
     use std::f32::consts::PI;
 
     #[test]
     fn inverse_project() {
         let m0 = Transform3D::identity();
         let p0 = Point2D::new(1.0, 2.0);
         // an identical transform doesn't need any inverse projection
         assert_eq!(m0.inverse_project(&p0), Some(p0));
@@ -511,17 +512,17 @@ pub mod test {
         let xref = LayoutTransform::create_scale(13.0, 8.0, 1.0);
         validate_convert(&xref);
 
         let xref = LayoutTransform::create_scale(0.5, 0.5, 1.0)
                         .pre_translate(LayoutVector3D::new(124.0, 38.0, 0.0));
         validate_convert(&xref);
 
         let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
-                        .pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
+                        .pre_transform(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
         validate_convert(&xref);
     }
 
     fn validate_inverse(xref: &LayoutTransform) {
         let s0 = ScaleOffset::from_transform(xref).unwrap();
         let s1 = s0.inverse().accumulate(&s0);
         assert!((s1.scale.x - 1.0).abs() < NEARLY_ZERO &&
                 (s1.scale.y - 1.0).abs() < NEARLY_ZERO &&
@@ -539,22 +540,22 @@ pub mod test {
         let xref = LayoutTransform::create_scale(13.0, 8.0, 1.0);
         validate_inverse(&xref);
 
         let xref = LayoutTransform::create_scale(0.5, 0.5, 1.0)
                         .pre_translate(LayoutVector3D::new(124.0, 38.0, 0.0));
         validate_inverse(&xref);
 
         let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
-                        .pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
+                        .pre_transform(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
         validate_inverse(&xref);
     }
 
     fn validate_accumulate(x0: &LayoutTransform, x1: &LayoutTransform) {
-        let x = x0.pre_mul(x1);
+        let x = x0.pre_transform(x1);
 
         let s0 = ScaleOffset::from_transform(x0).unwrap();
         let s1 = ScaleOffset::from_transform(x1).unwrap();
 
         let s = s0.accumulate(&s1).to_transform();
 
         assert!(x.approx_eq(&s), "{:?}\n{:?}", x, s);
     }
@@ -575,131 +576,131 @@ pub mod test {
         assert_eq!(m.inverse_project_2d_origin(), None);
         m.m21 = -2.0;
         m.m22 = 0.0;
         m.m12 = -0.5;
         m.m41 = 1.0;
         m.m42 = 0.5;
         let origin = m.inverse_project_2d_origin().unwrap();
         assert_eq!(origin, Point2D::new(1.0, 0.5));
-        assert_eq!(m.transform_point2d(&origin), Some(Point2D::zero()));
+        assert_eq!(m.transform_point2d(origin), Some(Point2D::zero()));
     }
 }
 
 pub trait MaxRect {
     fn max_rect() -> Self;
 }
 
 impl MaxRect for DeviceIntRect {
     fn max_rect() -> Self {
         DeviceIntRect::new(
             DeviceIntPoint::new(i32::MIN / 2, i32::MIN / 2),
             DeviceIntSize::new(i32::MAX, i32::MAX),
         )
     }
 }
 
-impl<U> MaxRect for TypedRect<f32, U> {
+impl<U> MaxRect for Rect<f32, U> {
     fn max_rect() -> Self {
         // Having an unlimited bounding box is fine up until we try
         // to cast it to `i32`, where we get `-2147483648` for any
         // values larger than or equal to 2^31.
         //
         // Note: clamping to i32::MIN and i32::MAX is not a solution,
         // with explanation left as an exercise for the reader.
         const MAX_COORD: f32 = 1.0e9;
 
-        TypedRect::new(
-            TypedPoint2D::new(-MAX_COORD, -MAX_COORD),
-            TypedSize2D::new(2.0 * MAX_COORD, 2.0 * MAX_COORD),
+        Rect::new(
+            Point2D::new(-MAX_COORD, -MAX_COORD),
+            Size2D::new(2.0 * MAX_COORD, 2.0 * MAX_COORD),
         )
     }
 }
 
 /// An enum that tries to avoid expensive transformation matrix calculations
 /// when possible when dealing with non-perspective axis-aligned transformations.
 #[derive(Debug, MallocSizeOf)]
 pub enum FastTransform<Src, Dst> {
     /// A simple offset, which can be used without doing any matrix math.
-    Offset(TypedVector2D<f32, Src>),
+    Offset(Vector2D<f32, Src>),
 
     /// A 2D transformation with an inverse.
     Transform {
-        transform: TypedTransform3D<f32, Src, Dst>,
-        inverse: Option<TypedTransform3D<f32, Dst, Src>>,
+        transform: Transform3D<f32, Src, Dst>,
+        inverse: Option<Transform3D<f32, Dst, Src>>,
         is_2d: bool,
     },
 }
 
 impl<Src, Dst> Clone for FastTransform<Src, Dst> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
 impl<Src, Dst> Copy for FastTransform<Src, Dst> { }
 
 impl<Src, Dst> FastTransform<Src, Dst> {
     pub fn identity() -> Self {
-        FastTransform::Offset(TypedVector2D::zero())
+        FastTransform::Offset(Vector2D::zero())
     }
 
-    pub fn with_vector(offset: TypedVector2D<f32, Src>) -> Self {
+    pub fn with_vector(offset: Vector2D<f32, Src>) -> Self {
         FastTransform::Offset(offset)
     }
 
     pub fn with_scale_offset(scale_offset: ScaleOffset) -> Self {
         if scale_offset.scale == Vector2D::new(1.0, 1.0) {
-            FastTransform::Offset(TypedVector2D::from_untyped(&scale_offset.offset))
+            FastTransform::Offset(Vector2D::from_untyped(scale_offset.offset))
         } else {
             FastTransform::Transform {
                 transform: scale_offset.to_transform(),
                 inverse: Some(scale_offset.inverse().to_transform()),
                 is_2d: true,
             }
         }
     }
 
     #[inline(always)]
-    pub fn with_transform(transform: TypedTransform3D<f32, Src, Dst>) -> Self {
+    pub fn with_transform(transform: Transform3D<f32, Src, Dst>) -> Self {
         if transform.is_simple_2d_translation() {
-            return FastTransform::Offset(TypedVector2D::new(transform.m41, transform.m42));
+            return FastTransform::Offset(Vector2D::new(transform.m41, transform.m42));
         }
         let inverse = transform.inverse();
         let is_2d = transform.is_2d();
         FastTransform::Transform { transform, inverse, is_2d}
     }
 
-    pub fn to_transform(&self) -> Cow<TypedTransform3D<f32, Src, Dst>> {
+    pub fn to_transform(&self) -> Cow<Transform3D<f32, Src, Dst>> {
         match *self {
             FastTransform::Offset(offset) => Cow::Owned(
-                TypedTransform3D::create_translation(offset.x, offset.y, 0.0)
+                Transform3D::create_translation(offset.x, offset.y, 0.0)
             ),
             FastTransform::Transform { ref transform, .. } => Cow::Borrowed(transform),
         }
     }
 
     /// Return true if this is an identity transform
     #[allow(unused)]
     pub fn is_identity(&self)-> bool {
         match *self {
             FastTransform::Offset(offset) => {
-                offset == TypedVector2D::zero()
+                offset == Vector2D::zero()
             }
             FastTransform::Transform { ref transform, .. } => {
-                *transform == TypedTransform3D::identity()
+                *transform == Transform3D::identity()
             }
         }
     }
 
-    pub fn post_mul<NewDst>(&self, other: &FastTransform<Dst, NewDst>) -> FastTransform<Src, NewDst> {
+    pub fn post_transform<NewDst>(&self, other: &FastTransform<Dst, NewDst>) -> FastTransform<Src, NewDst> {
         match *self {
             FastTransform::Offset(offset) => match *other {
                 FastTransform::Offset(other_offset) => {
-                    FastTransform::Offset(offset + other_offset * TypedScale::<_, _, Src>::new(1.0))
+                    FastTransform::Offset(offset + other_offset * Scale::<_, _, Src>::new(1.0))
                 }
                 FastTransform::Transform { transform: ref other_transform, .. } => {
                     FastTransform::with_transform(
                         other_transform
                             .with_source::<Src>()
                             .pre_translate(offset.to_3d())
                     )
                 }
@@ -709,47 +710,47 @@ impl<Src, Dst> FastTransform<Src, Dst> {
                     FastTransform::with_transform(
                         transform
                             .post_translate(other_offset.to_3d())
                             .with_destination::<NewDst>()
                     )
                 }
                 FastTransform::Transform { transform: ref other_transform, inverse: ref other_inverse, is_2d: other_is_2d } => {
                     FastTransform::Transform {
-                        transform: transform.post_mul(other_transform),
+                        transform: transform.post_transform(other_transform),
                         inverse: inverse.as_ref().and_then(|self_inv|
-                            other_inverse.as_ref().map(|other_inv| self_inv.pre_mul(other_inv))
+                            other_inverse.as_ref().map(|other_inv| self_inv.pre_transform(other_inv))
                         ),
                         is_2d: is_2d & other_is_2d,
                     }
                 }
             }
         }
     }
 
-    pub fn pre_mul<NewSrc>(
+    pub fn pre_transform<NewSrc>(
         &self,
         other: &FastTransform<NewSrc, Src>
     ) -> FastTransform<NewSrc, Dst> {
-        other.post_mul(self)
+        other.post_transform(self)
     }
 
-    pub fn pre_translate(&self, other_offset: &TypedVector2D<f32, Src>) -> Self {
+    pub fn pre_translate(&self, other_offset: Vector2D<f32, Src>) -> Self {
         match *self {
-            FastTransform::Offset(ref offset) =>
-                FastTransform::Offset(*offset + *other_offset),
+            FastTransform::Offset(offset) =>
+                FastTransform::Offset(offset + other_offset),
             FastTransform::Transform { transform, .. } =>
                 FastTransform::with_transform(transform.pre_translate(other_offset.to_3d()))
         }
     }
 
-    pub fn post_translate(&self, other_offset: &TypedVector2D<f32, Dst>) -> Self {
+    pub fn post_translate(&self, other_offset: Vector2D<f32, Dst>) -> Self {
         match *self {
-            FastTransform::Offset(ref offset) => {
-                FastTransform::Offset(*offset + *other_offset * TypedScale::<_, _, Src>::new(1.0))
+            FastTransform::Offset(offset) => {
+                FastTransform::Offset(offset + other_offset * Scale::<_, _, Src>::new(1.0))
             }
             FastTransform::Transform { ref transform, .. } => {
                 let transform = transform.post_translate(other_offset.to_3d());
                 FastTransform::with_transform(transform)
             }
         }
     }
 
@@ -760,70 +761,70 @@ impl<Src, Dst> FastTransform<Src, Dst> {
             FastTransform::Transform { inverse: None, .. } => false,
             //TODO: fix this properly by taking "det|M33| * det|M34| > 0"
             // see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23014
             FastTransform::Transform { inverse: Some(ref inverse), .. } => inverse.m33 < 0.0,
         }
     }
 
     #[inline(always)]
-    pub fn transform_point2d(&self, point: &TypedPoint2D<f32, Src>) -> Option<TypedPoint2D<f32, Dst>> {
+    pub fn transform_point2d(&self, point: Point2D<f32, Src>) -> Option<Point2D<f32, Dst>> {
         match *self {
             FastTransform::Offset(offset) => {
-                let new_point = *point + offset;
-                Some(TypedPoint2D::from_untyped(&new_point.to_untyped()))
+                let new_point = point + offset;
+                Some(Point2D::from_untyped(new_point.to_untyped()))
             }
             FastTransform::Transform { ref transform, .. } => transform.transform_point2d(point),
         }
     }
 
     #[inline(always)]
     pub fn inverse(&self) -> Option<FastTransform<Dst, Src>> {
         match *self {
             FastTransform::Offset(offset) =>
-                Some(FastTransform::Offset(TypedVector2D::new(-offset.x, -offset.y))),
+                Some(FastTransform::Offset(Vector2D::new(-offset.x, -offset.y))),
             FastTransform::Transform { transform, inverse: Some(inverse), is_2d, } =>
                 Some(FastTransform::Transform {
                     transform: inverse,
                     inverse: Some(transform),
                     is_2d
                 }),
             FastTransform::Transform { inverse: None, .. } => None,
 
         }
     }
 }
 
-impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
-    fn from(transform: TypedTransform3D<f32, Src, Dst>) -> Self {
+impl<Src, Dst> From<Transform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
+    fn from(transform: Transform3D<f32, Src, Dst>) -> Self {
         FastTransform::with_transform(transform)
     }
 }
 
-impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
-    fn from(vector: TypedVector2D<f32, Src>) -> Self {
+impl<Src, Dst> From<Vector2D<f32, Src>> for FastTransform<Src, Dst> {
+    fn from(vector: Vector2D<f32, Src>) -> Self {
         FastTransform::with_vector(vector)
     }
 }
 
 pub type LayoutFastTransform = FastTransform<LayoutPixel, LayoutPixel>;
 pub type LayoutToWorldFastTransform = FastTransform<LayoutPixel, WorldPixel>;
 
 pub fn project_rect<F, T>(
-    transform: &TypedTransform3D<f32, F, T>,
-    rect: &TypedRect<f32, F>,
-    bounds: &TypedRect<f32, T>,
-) -> Option<TypedRect<f32, T>>
+    transform: &Transform3D<f32, F, T>,
+    rect: &Rect<f32, F>,
+    bounds: &Rect<f32, T>,
+) -> Option<Rect<f32, T>>
  where F: fmt::Debug
 {
     let homogens = [
-        transform.transform_point2d_homogeneous(&rect.origin),
-        transform.transform_point2d_homogeneous(&rect.top_right()),
-        transform.transform_point2d_homogeneous(&rect.bottom_left()),
-        transform.transform_point2d_homogeneous(&rect.bottom_right()),
+        transform.transform_point2d_homogeneous(rect.origin),
+        transform.transform_point2d_homogeneous(rect.top_right()),
+        transform.transform_point2d_homogeneous(rect.bottom_left()),
+        transform.transform_point2d_homogeneous(rect.bottom_right()),
     ];
 
     // Note: we only do the full frustum collision when the polygon approaches the camera plane.
     // Otherwise, it will be clamped to the screen bounds anyway.
     if homogens.iter().any(|h| h.w <= 0.0) {
         let mut clipper = Clipper::new();
         let polygon = Polygon::from_rect(*rect, 1);
 
@@ -839,42 +840,42 @@ pub fn project_rect<F, T>(
             clipper.add(plane);
         }
 
         let results = clipper.clip(polygon);
         if results.is_empty() {
             return None
         }
 
-        Some(TypedRect::from_points(results
+        Some(Rect::from_points(results
             .into_iter()
             // filter out parts behind the view plane
             .flat_map(|poly| &poly.points)
             .map(|p| {
-                let mut homo = transform.transform_point2d_homogeneous(&p.to_2d());
+                let mut homo = transform.transform_point2d_homogeneous(p.to_2d());
                 homo.w = homo.w.max(0.00000001); // avoid infinite values
                 homo.to_point2d().unwrap()
             })
         ))
     } else {
         // we just checked for all the points to be in positive hemisphere, so `unwrap` is valid
-        Some(TypedRect::from_points(&[
+        Some(Rect::from_points(&[
             homogens[0].to_point2d().unwrap(),
             homogens[1].to_point2d().unwrap(),
             homogens[2].to_point2d().unwrap(),
             homogens[3].to_point2d().unwrap(),
         ]))
     }
 }
 
 pub fn raster_rect_to_device_pixels(
     rect: RasterRect,
     device_pixel_scale: DevicePixelScale,
 ) -> DeviceRect {
-    let world_rect = rect * TypedScale::new(1.0);
+    let world_rect = rect * Scale::new(1.0);
     let device_rect = world_rect * device_pixel_scale;
     device_rect.round_out()
 }
 
 /// Run the first callback over all elements in the array. If the callback returns true,
 /// the element is removed from the array and moved to a second callback.
 ///
 /// This is a simple implementation waiting for Vec::drain_filter to be stable.
@@ -1123,17 +1124,17 @@ impl<T: MallocSizeOf> MallocSizeOf for P
 /// Computes the scale factors of this matrix; that is,
 /// the amounts each basis vector is scaled by.
 ///
 /// This code comes from gecko gfx/2d/Matrix.h with the following
 /// modifications:
 ///
 /// * Removed `xMajor` parameter.
 pub fn scale_factors<Src, Dst>(
-    mat: &TypedTransform3D<f32, Src, Dst>
+    mat: &Transform3D<f32, Src, Dst>
 ) -> (f32, f32) {
     // Determinant is just of the 2D component.
     let det = mat.m11 * mat.m22 - mat.m12 * mat.m21;
     if det == 0.0 {
         return (0.0, 0.0);
     }
 
     // ignore mirroring
--- a/gfx/wr/webrender_api/Cargo.toml
+++ b/gfx/wr/webrender_api/Cargo.toml
@@ -15,17 +15,17 @@ deserialize = []
 display_list_stats = []
 
 [dependencies]
 app_units = "0.7"
 bitflags = "1.0"
 byteorder = "1.2.1"
 derive_more = "0.13"
 ipc-channel = {version = "0.11.0", optional = true}
-euclid = { version = "0.19.9", features = ["serde"] }
+euclid = { version = "0.20.0", features = ["serde"] }
 malloc_size_of_derive = "0.1"
 serde = { version = "=1.0.88", features = ["rc"] }
 serde_derive = "=1.0.88"
 serde_bytes = "0.10"
 time = "0.1"
 malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of", package = "wr_malloc_size_of" }
 peek-poke = { version = "0.2", path = "../peek-poke", features = ["extras"] }
 
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -201,17 +201,17 @@ impl StickyOffsetBounds {
 pub struct StickyFrameDisplayItem {
     pub id: SpatialId,
     pub parent_spatial_id: SpatialId,
     pub bounds: LayoutRect,
 
     /// The margins that should be maintained between the edge of the parent viewport and this
     /// sticky frame. A margin of None indicates that the sticky frame should not stick at all
     /// to that particular edge of the viewport.
-    pub margins: SideOffsets2D<Option<f32>>,
+    pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
 
     /// The minimum and maximum vertical offsets for this sticky frame. Ignoring these constraints,
     /// the sticky frame will continue to stick to the edge of the viewport as its original
     /// position is scrolled out of view. Constraints specify a maximum and minimum offset from the
     /// original position relative to non-sticky content within the same scrolling frame.
     pub vertical_offset_bounds: StickyOffsetBounds,
 
     /// The minimum and maximum horizontal offsets for this sticky frame. Ignoring these constraints,
@@ -419,33 +419,33 @@ pub struct NinePatchBorder {
 
     /// Distances from each edge where the image should be sliced up. These
     /// values are in 9-part-image space (the same space as width and height),
     /// and the resulting image parts will be used to fill the corresponding
     /// parts of the border as given by the border widths. This can lead to
     /// stretching.
     /// Slices can be overlapping. In that case, the same pixels from the
     /// 9-part image will show up in multiple parts of the resulting border.
-    pub slice: SideOffsets2D<i32>,
+    pub slice: DeviceIntSideOffsets,
 
     /// Controls whether the center of the 9 patch image is rendered or
     /// ignored. The center is never rendered if the slices are overlapping.
     pub fill: bool,
 
     /// Determines what happens if the horizontal side parts of the 9-part
     /// image have a different size than the horizontal parts of the border.
     pub repeat_horizontal: RepeatMode,
 
     /// Determines what happens if the vertical side parts of the 9-part
     /// image have a different size than the vertical parts of the border.
     pub repeat_vertical: RepeatMode,
 
     /// The outset for the border.
     /// TODO(mrobinson): This should be removed and handled by the client.
-    pub outset: SideOffsets2D<f32>,
+    pub outset: LayoutSideOffsets, // TODO: what unit is this in?
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
 pub enum BorderDetails {
     Normal(NormalBorder),
     NinePatch(NinePatchBorder),
 }
 
--- a/gfx/wr/webrender_api/src/display_list.rs
+++ b/gfx/wr/webrender_api/src/display_list.rs
@@ -1403,17 +1403,17 @@ impl DisplayListBuilder {
         self.push_iter(complex_clips);
         id
     }
 
     pub fn define_sticky_frame(
         &mut self,
         parent_spatial_id: di::SpatialId,
         frame_rect: LayoutRect,
-        margins: SideOffsets2D<Option<f32>>,
+        margins: SideOffsets2D<Option<f32>, LayoutPixel>,
         vertical_offset_bounds: di::StickyOffsetBounds,
         horizontal_offset_bounds: di::StickyOffsetBounds,
         previously_applied_offset: LayoutVector2D,
     ) -> di::SpatialId {
         let id = self.generate_spatial_index();
         let item = di::DisplayItem::StickyFrame(di::StickyFrameDisplayItem {
             parent_spatial_id,
             id,
--- a/gfx/wr/webrender_api/src/image.rs
+++ b/gfx/wr/webrender_api/src/image.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![deny(missing_docs)]
 
-use euclid::{size2, TypedRect, num::Zero};
+use euclid::{size2, Rect, num::Zero};
 use peek_poke::PeekPoke;
 use std::ops::{Add, Sub};
 use std::sync::Arc;
 // local imports
 use crate::api::{IdNamespace, TileSize};
 use crate::font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
 use crate::units::*;
 
@@ -376,30 +376,30 @@ pub struct BlobImageParams {
 /// The possible states of a Dirty rect.
 ///
 /// This exists because people kept getting confused with `Option<Rect>`.
 #[derive(Debug, Serialize, Deserialize)]
 pub enum DirtyRect<T: Copy, U> {
     /// Everything is Dirty, equivalent to Partial(image_bounds)
     All,
     /// Some specific amount is dirty
-    Partial(TypedRect<T, U>)
+    Partial(Rect<T, U>)
 }
 
 impl<T, U> DirtyRect<T, U>
 where
     T: Copy + Clone
         + PartialOrd + PartialEq
         + Add<T, Output = T>
         + Sub<T, Output = T>
         + Zero
 {
     /// Creates an empty DirtyRect (indicating nothing is invalid)
     pub fn empty() -> Self {
-        DirtyRect::Partial(TypedRect::zero())
+        DirtyRect::Partial(Rect::zero())
     }
 
     /// Returns whether the dirty rect is empty
     pub fn is_empty(&self) -> bool {
         match self {
             DirtyRect::All => false,
             DirtyRect::Partial(rect) => rect.is_empty(),
         }
@@ -407,17 +407,17 @@ where
 
     /// Replaces self with the empty rect and returns the old value.
     pub fn replace_with_empty(&mut self) -> Self {
         ::std::mem::replace(self, DirtyRect::empty())
     }
 
     /// Maps over the contents of Partial.
     pub fn map<F>(self, func: F) -> Self
-        where F: FnOnce(TypedRect<T, U>) -> TypedRect<T, U>,
+        where F: FnOnce(Rect<T, U>) -> Rect<T, U>,
     {
         use crate::DirtyRect::*;
 
         match self {
             All        => All,
             Partial(rect) => Partial(func(rect)),
         }
     }
@@ -434,39 +434,39 @@ where
 
     /// Intersects the dirty rects.
     pub fn intersection(&self, other: &Self) -> Self {
         use crate::DirtyRect::*;
 
         match (*self, *other) {
             (All, rect) | (rect, All)  => rect,
             (Partial(rect1), Partial(rect2)) => Partial(rect1.intersection(&rect2)
-                                                                   .unwrap_or_else(TypedRect::zero))
+                                                                   .unwrap_or_else(Rect::zero))
         }
     }
 
     /// Converts the dirty rect into a subrect of the given one via intersection.
-    pub fn to_subrect_of(&self, rect: &TypedRect<T, U>) -> TypedRect<T, U> {
+    pub fn to_subrect_of(&self, rect: &Rect<T, U>) -> Rect<T, U> {
         use crate::DirtyRect::*;
 
         match *self {
             All              => *rect,
             Partial(dirty_rect) => dirty_rect.intersection(rect)
-                                               .unwrap_or_else(TypedRect::zero),
+                                               .unwrap_or_else(Rect::zero),
         }
     }
 }
 
 impl<T: Copy, U> Copy for DirtyRect<T, U> {}
 impl<T: Copy, U> Clone for DirtyRect<T, U> {
     fn clone(&self) -> Self { *self }
 }
 
-impl<T: Copy, U> From<TypedRect<T, U>> for DirtyRect<T, U> {
-    fn from(rect: TypedRect<T, U>) -> Self {
+impl<T: Copy, U> From<Rect<T, U>> for DirtyRect<T, U> {
+    fn from(rect: Rect<T, U>) -> Self {
         DirtyRect::Partial(rect)
     }
 }
 
 /// Backing store for blob image command streams.
 pub type BlobImageData = Vec<u8>;
 
 /// Result type for blob raserization.
--- a/gfx/wr/webrender_api/src/units.rs
+++ b/gfx/wr/webrender_api/src/units.rs
@@ -8,145 +8,145 @@
 //! to correspond to the allocated size of resources in memory, while logical pixels
 //! don't have the device pixel ratio applied which means they are agnostic to the usage
 //! of hidpi screens and the like.
 //!
 //! The terms "layer" and "stacking context" can be used interchangeably
 //! in the context of coordinate systems.
 
 pub use app_units::Au;
-use euclid::{Length, TypedRect, TypedScale, TypedSize2D, TypedTransform3D, TypedTranslation2D};
-use euclid::{TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, TypedSideOffsets2D};
+use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
+use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D};
 use euclid::HomogeneousVector;
 use peek_poke::PeekPoke;
 // local imports
 use crate::image::DirtyRect;
 
 /// Geometry in the coordinate system of the render target (screen or intermediate
 /// surface) in physical pixels.
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
 pub struct DevicePixel;
 
-pub type DeviceIntRect = TypedRect<i32, DevicePixel>;
-pub type DeviceIntPoint = TypedPoint2D<i32, DevicePixel>;
-pub type DeviceIntSize = TypedSize2D<i32, DevicePixel>;
+pub type DeviceIntRect = Rect<i32, DevicePixel>;
+pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
+pub type DeviceIntSize = Size2D<i32, DevicePixel>;
 pub type DeviceIntLength = Length<i32, DevicePixel>;
-pub type DeviceIntSideOffsets = TypedSideOffsets2D<i32, DevicePixel>;
+pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
 
-pub type DeviceRect = TypedRect<f32, DevicePixel>;
-pub type DevicePoint = TypedPoint2D<f32, DevicePixel>;
-pub type DeviceVector2D = TypedVector2D<f32, DevicePixel>;
-pub type DeviceSize = TypedSize2D<f32, DevicePixel>;
+pub type DeviceRect = Rect<f32, DevicePixel>;
+pub type DevicePoint = Point2D<f32, DevicePixel>;
+pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
+pub type DeviceSize = Size2D<f32, DevicePixel>;
 pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
 
 /// Geometry in the coordinate system of the framebuffer in physical pixels.
 /// It's Y-flipped comparing to DevicePixel.
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
 pub struct FramebufferPixel;
 
-pub type FramebufferIntPoint = TypedPoint2D<i32, FramebufferPixel>;
-pub type FramebufferIntSize = TypedSize2D<i32, FramebufferPixel>;
-pub type FramebufferIntRect = TypedRect<i32, FramebufferPixel>;
+pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
+pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
+pub type FramebufferIntRect = Rect<i32, FramebufferPixel>;
 
 /// Geometry in the coordinate system of a Picture (intermediate
 /// surface) in physical pixels.
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct PicturePixel;
 
-pub type PictureIntRect = TypedRect<i32, PicturePixel>;
-pub type PictureIntPoint = TypedPoint2D<i32, PicturePixel>;
-pub type PictureIntSize = TypedSize2D<i32, PicturePixel>;
-pub type PictureRect = TypedRect<f32, PicturePixel>;
-pub type PicturePoint = TypedPoint2D<f32, PicturePixel>;
-pub type PictureSize = TypedSize2D<f32, PicturePixel>;
-pub type PicturePoint3D = TypedPoint3D<f32, PicturePixel>;
-pub type PictureVector2D = TypedVector2D<f32, PicturePixel>;
-pub type PictureVector3D = TypedVector3D<f32, PicturePixel>;
+pub type PictureIntRect = Rect<i32, PicturePixel>;
+pub type PictureIntPoint = Point2D<i32, PicturePixel>;
+pub type PictureIntSize = Size2D<i32, PicturePixel>;
+pub type PictureRect = Rect<f32, PicturePixel>;
+pub type PicturePoint = Point2D<f32, PicturePixel>;
+pub type PictureSize = Size2D<f32, PicturePixel>;
+pub type PicturePoint3D = Point3D<f32, PicturePixel>;
+pub type PictureVector2D = Vector2D<f32, PicturePixel>;
+pub type PictureVector3D = Vector3D<f32, PicturePixel>;
 
 /// Geometry gets rasterized in a given root coordinate space. This
 /// is often the root spatial node (world space), but may be a local
 /// space for a variety of reasons (e.g. perspective).
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct RasterPixel;
 
-pub type RasterIntRect = TypedRect<i32, RasterPixel>;
-pub type RasterIntPoint = TypedPoint2D<i32, RasterPixel>;
-pub type RasterIntSize = TypedSize2D<i32, RasterPixel>;
-pub type RasterRect = TypedRect<f32, RasterPixel>;
-pub type RasterPoint = TypedPoint2D<f32, RasterPixel>;
-pub type RasterSize = TypedSize2D<f32, RasterPixel>;
-pub type RasterPoint3D = TypedPoint3D<f32, RasterPixel>;
-pub type RasterVector2D = TypedVector2D<f32, RasterPixel>;
-pub type RasterVector3D = TypedVector3D<f32, RasterPixel>;
+pub type RasterIntRect = Rect<i32, RasterPixel>;
+pub type RasterIntPoint = Point2D<i32, RasterPixel>;
+pub type RasterIntSize = Size2D<i32, RasterPixel>;
+pub type RasterRect = Rect<f32, RasterPixel>;
+pub type RasterPoint = Point2D<f32, RasterPixel>;
+pub type RasterSize = Size2D<f32, RasterPixel>;
+pub type RasterPoint3D = Point3D<f32, RasterPixel>;
+pub type RasterVector2D = Vector2D<f32, RasterPixel>;
+pub type RasterVector3D = Vector3D<f32, RasterPixel>;
 
 /// Geometry in a stacking context's local coordinate space (logical pixels).
 #[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
 pub struct LayoutPixel;
 
-pub type LayoutRect = TypedRect<f32, LayoutPixel>;
-pub type LayoutPoint = TypedPoint2D<f32, LayoutPixel>;
-pub type LayoutPoint3D = TypedPoint3D<f32, LayoutPixel>;
-pub type LayoutVector2D = TypedVector2D<f32, LayoutPixel>;
-pub type LayoutVector3D = TypedVector3D<f32, LayoutPixel>;
-pub type LayoutSize = TypedSize2D<f32, LayoutPixel>;
-pub type LayoutSideOffsets = TypedSideOffsets2D<f32, LayoutPixel>;
+pub type LayoutRect = Rect<f32, LayoutPixel>;
+pub type LayoutPoint = Point2D<f32, LayoutPixel>;
+pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
+pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
+pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
+pub type LayoutSize = Size2D<f32, LayoutPixel>;
+pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
 
-pub type LayoutIntRect = TypedRect<i32, LayoutPixel>;
-pub type LayoutIntPoint = TypedPoint2D<i32, LayoutPixel>;
-pub type LayoutIntSize = TypedSize2D<i32, LayoutPixel>;
+pub type LayoutIntRect = Rect<i32, LayoutPixel>;
+pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
+pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
 
 /// Geometry in the document's coordinate space (logical pixels).
 #[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)]
 pub struct WorldPixel;
 
-pub type WorldRect = TypedRect<f32, WorldPixel>;
-pub type WorldPoint = TypedPoint2D<f32, WorldPixel>;
-pub type WorldSize = TypedSize2D<f32, WorldPixel>;
-pub type WorldPoint3D = TypedPoint3D<f32, WorldPixel>;
-pub type WorldVector2D = TypedVector2D<f32, WorldPixel>;
-pub type WorldVector3D = TypedVector3D<f32, WorldPixel>;
+pub type WorldRect = Rect<f32, WorldPixel>;
+pub type WorldPoint = Point2D<f32, WorldPixel>;
+pub type WorldSize = Size2D<f32, WorldPixel>;
+pub type WorldPoint3D = Point3D<f32, WorldPixel>;
+pub type WorldVector2D = Vector2D<f32, WorldPixel>;
+pub type WorldVector3D = Vector3D<f32, WorldPixel>;
 
 /// Offset in number of tiles.
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct Tiles;
-pub type TileOffset = TypedPoint2D<i32, Tiles>;
-pub type TileRange = TypedRect<i32, Tiles>;
+pub type TileOffset = Point2D<i32, Tiles>;
+pub type TileRange = Rect<i32, Tiles>;
 
 /// Scaling ratio from world pixels to device pixels.
-pub type DevicePixelScale = TypedScale<f32, WorldPixel, DevicePixel>;
+pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
 /// Scaling ratio from layout to world. Used for cases where we know the layout
 /// is in world space, or specifically want to treat it this way.
-pub type LayoutToWorldScale = TypedScale<f32, LayoutPixel, WorldPixel>;
+pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
 /// A complete scaling ratio from layout space to device pixel space.
-pub type LayoutToDeviceScale = TypedScale<f32, LayoutPixel, DevicePixel>;
+pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
 
-pub type LayoutTransform = TypedTransform3D<f32, LayoutPixel, LayoutPixel>;
-pub type LayoutToWorldTransform = TypedTransform3D<f32, LayoutPixel, WorldPixel>;
-pub type WorldToLayoutTransform = TypedTransform3D<f32, WorldPixel, LayoutPixel>;
+pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
+pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
+pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
 
-pub type LayoutToPictureTransform = TypedTransform3D<f32, LayoutPixel, PicturePixel>;
-pub type PictureToLayoutTransform = TypedTransform3D<f32, PicturePixel, LayoutPixel>;
+pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
+pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
 
-pub type LayoutToRasterTransform = TypedTransform3D<f32, LayoutPixel, RasterPixel>;
-pub type RasterToLayoutTransform = TypedTransform3D<f32, RasterPixel, LayoutPixel>;
+pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
+pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
 
-pub type PictureToRasterTransform = TypedTransform3D<f32, PicturePixel, RasterPixel>;
-pub type RasterToPictureTransform = TypedTransform3D<f32, RasterPixel, PicturePixel>;
+pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
+pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
 
 // Fixed position coordinates, to avoid float precision errors.
-pub type LayoutPointAu = TypedPoint2D<Au, LayoutPixel>;
-pub type LayoutRectAu = TypedRect<Au, LayoutPixel>;
-pub type LayoutSizeAu = TypedSize2D<Au, LayoutPixel>;
-pub type LayoutVector2DAu = TypedVector2D<Au, LayoutPixel>;
-pub type LayoutSideOffsetsAu = TypedSideOffsets2D<Au, LayoutPixel>;
+pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
+pub type LayoutRectAu = Rect<Au, LayoutPixel>;
+pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
+pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
+pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
 
 pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
 pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
 
-pub type BlobToDeviceTranslation = TypedTranslation2D<i32, LayoutPixel, DevicePixel>;
+pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
 
 /// Stores two coordinates in texel space. The coordinates
 /// are stored in texel coordinates because the texture atlas
 /// may grow. Storing them as texel coords and normalizing
 /// the UVs in the vertex shader means nothing needs to be
 /// updated on the CPU when the texture size changes.
 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
 pub struct TexelRect {
@@ -261,8 +261,32 @@ impl AuHelpers<LayoutSideOffsetsAu> for 
         LayoutSideOffsetsAu::new(
             Au::from_f32_px(self.top),
             Au::from_f32_px(self.right),
             Au::from_f32_px(self.bottom),
             Au::from_f32_px(self.left),
         )
     }
 }
+
+pub trait RectExt {
+    type Point;
+    fn top_left(&self) -> Self::Point;
+    fn top_right(&self) -> Self::Point;
+    fn bottom_left(&self) -> Self::Point;
+    fn bottom_right(&self) -> Self::Point;
+}
+
+impl<U> RectExt for Rect<f32, U> {
+    type Point = Point2D<f32, U>;
+    fn top_left(&self) -> Self::Point {
+        self.min()
+    }
+    fn top_right(&self) -> Self::Point {
+        Point2D::new(self.max_x(), self.min_y())
+    }
+    fn bottom_left(&self) -> Self::Point {
+        Point2D::new(self.min_x(), self.max_y())
+    }
+    fn bottom_right(&self) -> Self::Point {
+        self.max()
+    }
+}
--- a/gfx/wr/wr_malloc_size_of/Cargo.toml
+++ b/gfx/wr/wr_malloc_size_of/Cargo.toml
@@ -6,9 +6,9 @@ version = "0.0.1"
 license = "MIT/Apache-2.0"
 edition = "2018"
 
 [lib]
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.7"
-euclid = "0.19"
+euclid = "0.20"
--- a/gfx/wr/wr_malloc_size_of/lib.rs
+++ b/gfx/wr/wr_malloc_size_of/lib.rs
@@ -311,61 +311,61 @@ impl<T> MallocSizeOf for std::marker::Ph
 }
 
 impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.0.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedScale<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.0.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.x.size_of(ops) + self.y.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.origin.size_of(ops) + self.size.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.top.size_of(ops) +
             self.right.size_of(ops) +
             self.bottom.size_of(ops) +
             self.left.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.width.size_of(ops) + self.height.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.m11.size_of(ops) +
             self.m12.size_of(ops) +
             self.m21.size_of(ops) +
             self.m22.size_of(ops) +
             self.m31.size_of(ops) +
             self.m32.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.m11.size_of(ops) +
             self.m12.size_of(ops) +
             self.m13.size_of(ops) +
             self.m14.size_of(ops) +
             self.m21.size_of(ops) +
             self.m22.size_of(ops) +
             self.m23.size_of(ops) +
@@ -376,17 +376,17 @@ impl<T: MallocSizeOf, Src, Dst> MallocSi
             self.m34.size_of(ops) +
             self.m41.size_of(ops) +
             self.m42.size_of(ops) +
             self.m43.size_of(ops) +
             self.m44.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.x.size_of(ops) + self.y.size_of(ops)
     }
 }
 
 /// For use on types where size_of() returns 0.
 #[macro_export]
 macro_rules! malloc_size_of_is_0(
--- a/gfx/wr/wrench/Cargo.toml
+++ b/gfx/wr/wrench/Cargo.toml
@@ -6,17 +6,17 @@ build = "build.rs"
 license = "MPL-2.0"
 edition = "2018"
 
 [dependencies]
 base64 = "0.10"
 bincode = "1.0"
 byteorder = "1.0"
 env_logger = { version = "0.5", optional = true }
-euclid = "0.19"
+euclid = "0.20"
 gleam = "0.6.2"
 glutin = "0.21"
 app_units = "0.7"
 image = "0.21"
 clap = { version = "2", features = ["yaml"] }
 lazy_static = "1"
 log = "0.4"
 yaml-rust = "0.4"
--- a/gfx/wr/wrench/src/yaml_frame_writer.rs
+++ b/gfx/wr/wrench/src/yaml_frame_writer.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 extern crate yaml_rust;
 
-use euclid::{TypedPoint2D, TypedRect, TypedSize2D, TypedTransform3D, TypedVector2D};
+use euclid::{Point2D, Rect, Size2D, Transform3D, Vector2D};
 use image::{save_buffer, ColorType};
 use crate::premultiply::unpremultiply;
 use crate::scene::{Scene, SceneProperties};
 use std::collections::HashMap;
 use std::io::Write;
 use std::path::{Path, PathBuf};
 use std::{fmt, fs};
 use super::CURRENT_FRAME_NUMBER;
@@ -79,45 +79,45 @@ fn filter_input_to_string(input: FilterP
         FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => index.to_string(),
     }
 }
 
 fn color_node(parent: &mut Table, key: &str, value: ColorF) {
     yaml_node(parent, key, Yaml::String(color_to_string(value)));
 }
 
-fn point_node<U>(parent: &mut Table, key: &str, value: &TypedPoint2D<f32, U>) {
+fn point_node<U>(parent: &mut Table, key: &str, value: &Point2D<f32, U>) {
     f32_vec_node(parent, key, &[value.x, value.y]);
 }
 
-fn vector_node<U>(parent: &mut Table, key: &str, value: &TypedVector2D<f32, U>) {
+fn vector_node<U>(parent: &mut Table, key: &str, value: &Vector2D<f32, U>) {
     f32_vec_node(parent, key, &[value.x, value.y]);
 }
 
-fn size_node<U>(parent: &mut Table, key: &str, value: &TypedSize2D<f32, U>) {
+fn size_node<U>(parent: &mut Table, key: &str, value: &Size2D<f32, U>) {
     f32_vec_node(parent, key, &[value.width, value.height]);
 }
 
-fn rect_yaml<U>(value: &TypedRect<f32, U>) -> Yaml {
+fn rect_yaml<U>(value: &Rect<f32, U>) -> Yaml {
     f32_vec_yaml(
         &[
             value.origin.x,
             value.origin.y,
             value.size.width,
             value.size.height,
         ],
         false,
     )
 }
 
-fn rect_node<U>(parent: &mut Table, key: &str, value: &TypedRect<f32, U>) {
+fn rect_node<U>(parent: &mut Table, key: &str, value: &Rect<f32, U>) {
     yaml_node(parent, key, rect_yaml(value));
 }
 
-fn matrix4d_node<U1, U2>(parent: &mut Table, key: &str, value: &TypedTransform3D<f32, U1, U2>) {
+fn matrix4d_node<U1, U2>(parent: &mut Table, key: &str, value: &Transform3D<f32, U1, U2>) {
     f32_vec_node(parent, key, &value.to_row_major_array());
 }
 
 fn u32_node(parent: &mut Table, key: &str, value: u32) {
     yaml_node(parent, key, Yaml::Integer(value as i64));
 }
 
 fn i32_node(parent: &mut Table, key: &str, value: i32) {
--- a/gfx/wr/wrench/src/yaml_helper.rs
+++ b/gfx/wr/wrench/src/yaml_helper.rs
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use euclid::{Angle, TypedSize2D};
+use euclid::{Angle, Size2D};
 use crate::parse_function::parse_function;
 use std::f32;
 use std::str::FromStr;
 use webrender::api::*;
 use webrender::api::units::*;
 use yaml_rust::{Yaml, YamlLoader};
 
 pub trait YamlHelper {
@@ -174,27 +174,27 @@ fn make_rotation(
 ) -> LayoutTransform {
     let pre_transform = LayoutTransform::create_translation(origin.x, origin.y, 0.0);
     let post_transform = LayoutTransform::create_translation(-origin.x, -origin.y, -0.0);
 
     let theta = 2.0f32 * f32::consts::PI - degrees.to_radians();
     let transform =
         LayoutTransform::identity().pre_rotate(axis_x, axis_y, axis_z, Angle::radians(theta));
 
-    pre_transform.pre_mul(&transform).pre_mul(&post_transform)
+    pre_transform.pre_transform(&transform).pre_transform(&post_transform)
 }
 
 pub fn make_perspective(
     origin: LayoutPoint,
     perspective: f32,
 ) -> LayoutTransform {
     let pre_transform = LayoutTransform::create_translation(origin.x, origin.y, 0.0);
     let post_transform = LayoutTransform::create_translation(-origin.x, -origin.y, -0.0);
     let transform = LayoutTransform::create_perspective(perspective);
-    pre_transform.pre_mul(&transform).pre_mul(&post_transform)
+    pre_transform.pre_transform(&transform).pre_transform(&post_transform)
 }
 
 // Create a skew matrix, specified in degrees.
 fn make_skew(
     skew_x: f32,
     skew_y: f32,
 ) -> LayoutTransform {
     let alpha = Angle::radians(skew_x.to_radians());
@@ -417,25 +417,25 @@ impl YamlHelper for Yaml {
                         "perspective" if args.len() == 1 => {
                             LayoutTransform::create_perspective(args[0].parse().unwrap())
                         }
                         _ => {
                             println!("unknown function {}", function);
                             break;
                         }
                     };
-                    transform = transform.post_mul(&mx);
+                    transform = transform.post_transform(&mx);
                 }
                 Some(transform)
             }
             Yaml::Array(ref array) => {
                 let transform = array.iter().fold(
                     LayoutTransform::identity(),
                     |u, yaml| match yaml.as_transform(transform_origin) {
-                        Some(ref transform) => u.pre_mul(transform),
+                        Some(ref transform) => u.pre_transform(transform),
                         None => u,
                     },
                 );
                 Some(transform)
             }
             Yaml::BadValue => None,
             _ => {
                 println!("unknown transform {:?}", self);
@@ -492,17 +492,17 @@ impl YamlHelper for Yaml {
             None
         }
     }
 
     fn as_border_radius_component(&self) -> LayoutSize {
         if let Yaml::Integer(integer) = *self {
             return LayoutSize::new(integer as f32, integer as f32);
         }
-        self.as_size().unwrap_or(TypedSize2D::zero())
+        self.as_size().unwrap_or(Size2D::zero())
     }
 
     fn as_border_radius(&self) -> Option<BorderRadius> {
         if let Some(size) = self.as_size() {
             return Some(BorderRadius::uniform_size(size));
         }
 
         match *self {
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -3647,18 +3647,18 @@ ImgDrawResult nsCSSBorderImageRenderer::
       }
 
       wr::WrBorderImage params{
           wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
           key.value(),
           mImageSize.width / appUnitsPerDevPixel,
           mImageSize.height / appUnitsPerDevPixel,
           mFill,
-          wr::ToSideOffsets2D_i32(slice[0], slice[1], slice[2], slice[3]),
-          wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]),
+          wr::ToDeviceIntSideOffsets(slice[0], slice[1], slice[2], slice[3]),
+          wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2], outset[3]),
           wr::ToRepeatMode(mRepeatModeHorizontal),
           wr::ToRepeatMode(mRepeatModeVertical)};
 
       aBuilder.PushBorderImage(dest, clip, !aItem->BackfaceIsHidden(), params);
       break;
     }
     case eStyleImageType_Gradient: {
       const StyleGradient& gradient = *mImageRenderer.GetGradientData();
@@ -3679,28 +3679,28 @@ ImgDrawResult nsCSSBorderImageRenderer::
         LayoutDevicePoint endPoint =
             LayoutDevicePoint(dest.origin.x, dest.origin.y) + lineEnd;
 
         aBuilder.PushBorderGradient(
             dest, clip, !aItem->BackfaceIsHidden(),
             wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
             (float)(mImageSize.width) / appUnitsPerDevPixel,
             (float)(mImageSize.height) / appUnitsPerDevPixel, mFill,
-            wr::ToSideOffsets2D_i32(slice[0], slice[1], slice[2], slice[3]),
+            wr::ToDeviceIntSideOffsets(slice[0], slice[1], slice[2], slice[3]),
             wr::ToLayoutPoint(startPoint), wr::ToLayoutPoint(endPoint), stops,
             extendMode,
-            wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2],
+            wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2],
                                     outset[3]));
       } else {
         aBuilder.PushBorderRadialGradient(
             dest, clip, !aItem->BackfaceIsHidden(),
             wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
             mFill, wr::ToLayoutPoint(lineStart),
             wr::ToLayoutSize(gradientRadius), stops, extendMode,
-            wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2],
+            wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2],
                                     outset[3]));
       }
       break;
     }
     default:
       MOZ_ASSERT_UNREACHABLE("Unsupport border image type");
       drawResult = ImgDrawResult::NOT_SUPPORTED;
   }
--- a/servo/components/malloc_size_of/Cargo.toml
+++ b/servo/components/malloc_size_of/Cargo.toml
@@ -22,17 +22,17 @@ servo = [
     "webrender_api",
     "xml5ever",
 ]
 
 [dependencies]
 app_units = "0.7"
 crossbeam-channel = { version = "0.3", optional = true }
 cssparser = "0.25"
-euclid = "0.19"
+euclid = "0.20"
 hashglobe = { path = "../hashglobe" }
 hyper = { version = "0.12", optional = true }
 hyper_serde = { version = "0.11", optional = true }
 keyboard-types = {version = "0.4.3", optional = true}
 selectors = { path = "../selectors" }
 serde = { version = "1.0.27", optional = true }
 serde_bytes = { version = "0.10", optional = true }
 servo_arc = { path = "../servo_arc" }
--- a/servo/components/malloc_size_of/lib.rs
+++ b/servo/components/malloc_size_of/lib.rs
@@ -620,61 +620,61 @@ impl MallocSizeOf for smallbitvec::Small
 }
 
 impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.0.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedScale<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.0.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.x.size_of(ops) + self.y.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.origin.size_of(ops) + self.size.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.top.size_of(ops) +
             self.right.size_of(ops) +
             self.bottom.size_of(ops) +
             self.left.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.width.size_of(ops) + self.height.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.m11.size_of(ops) +
             self.m12.size_of(ops) +
             self.m21.size_of(ops) +
             self.m22.size_of(ops) +
             self.m31.size_of(ops) +
             self.m32.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
+impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.m11.size_of(ops) +
             self.m12.size_of(ops) +
             self.m13.size_of(ops) +
             self.m14.size_of(ops) +
             self.m21.size_of(ops) +
             self.m22.size_of(ops) +
             self.m23.size_of(ops) +
@@ -685,17 +685,17 @@ impl<T: MallocSizeOf, Src, Dst> MallocSi
             self.m34.size_of(ops) +
             self.m41.size_of(ops) +
             self.m42.size_of(ops) +
             self.m43.size_of(ops) +
             self.m44.size_of(ops)
     }
 }
 
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
+impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         self.x.size_of(ops) + self.y.size_of(ops)
     }
 }
 
 impl MallocSizeOf for selectors::parser::AncestorHashes {
     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
         let selectors::parser::AncestorHashes { ref packed_hashes } = *self;
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -30,17 +30,17 @@ arrayvec = "0.4.6"
 atomic_refcell = "0.1"
 bitflags = "1.0"
 byteorder = "1.0"
 cssparser = "0.25"
 crossbeam-channel = { version = "0.3", optional = true }
 derive_more = "0.13"
 new_debug_unreachable = "1.0"
 encoding_rs = {version = "0.8", optional = true}
-euclid = "0.19"
+euclid = "0.20"
 fallible = { path = "../fallible" }
 fxhash = "0.2"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.23", optional = true}
 indexmap = "1.0"
 itertools = "0.7.6"
 itoa = "0.4"
 lazy_static = "1"
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -26,18 +26,18 @@ use crate::sharing::StyleSharingCache;
 use crate::stylist::Stylist;
 use crate::thread_state::{self, ThreadState};
 use crate::timer::Timer;
 use crate::traversal::DomTraversal;
 use crate::traversal_flags::TraversalFlags;
 use app_units::Au;
 #[cfg(feature = "servo")]
 use crossbeam_channel::Sender;
-use euclid::Size2D;
-use euclid::TypedScale;
+use euclid::default::Size2D;
+use euclid::Scale;
 use fxhash::FxHashMap;
 #[cfg(feature = "servo")]
 use parking_lot::RwLock;
 use selectors::matching::ElementSelectorFlags;
 use selectors::NthIndexCache;
 use servo_arc::Arc;
 #[cfg(feature = "servo")]
 use servo_atoms::Atom;
@@ -190,17 +190,17 @@ pub struct SharedStyleContext<'a> {
 
 impl<'a> SharedStyleContext<'a> {
     /// Return a suitable viewport size in order to be used for viewport units.
     pub fn viewport_size(&self) -> Size2D<Au> {
         self.stylist.device().au_viewport_size()
     }
 
     /// The device pixel ratio
-    pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
+    pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
         self.stylist.device().device_pixel_ratio()
     }
 
     /// The quirks mode of the document.
     pub fn quirks_mode(&self) -> QuirksMode {
         self.stylist.quirks_mode()
     }
 }
--- a/servo/components/style/gecko/media_features.rs
+++ b/servo/components/style/gecko/media_features.rs
@@ -9,17 +9,17 @@ use crate::gecko_bindings::structs;
 use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
 use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
 use crate::media_queries::media_feature_expression::{AspectRatio, RangeOrOperator};
 use crate::media_queries::{Device, MediaType};
 use crate::values::computed::CSSPixelLength;
 use crate::values::computed::Resolution;
 use crate::Atom;
 use app_units::Au;
-use euclid::Size2D;
+use euclid::default::Size2D;
 
 fn viewport_size(device: &Device) -> Size2D<Au> {
     if let Some(pc) = device.pres_context() {
         if pc.mIsRootPaginatedDocument() != 0 {
             // We want the page size, including unprintable areas and margins.
             // FIXME(emilio, bug 1414600): Not quite!
             let area = &pc.mPageSize;
             return Size2D::new(Au(area.width), Au(area.height));
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -11,18 +11,18 @@ use crate::gecko_bindings::structs;
 use crate::media_queries::MediaType;
 use crate::properties::ComputedValues;
 use crate::string_cache::Atom;
 use crate::values::computed::font::FontSize;
 use crate::values::{CustomIdent, KeyframesName};
 use app_units::Au;
 use app_units::AU_PER_PX;
 use cssparser::RGBA;
-use euclid::Size2D;
-use euclid::TypedScale;
+use euclid::default::Size2D;
+use euclid::Scale;
 use servo_arc::Arc;
 use std::fmt;
 use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
 use style_traits::viewport::ViewportConstraints;
 use style_traits::{CSSPixel, DevicePixel};
 
 /// The `Device` in Gecko wraps a pres context, has a default values computed,
 /// and contains all the viewport rule state.
@@ -242,30 +242,30 @@ impl Device {
     }
 
     /// Returns whether we ever looked up the viewport size of the Device.
     pub fn used_viewport_size(&self) -> bool {
         self.used_viewport_size.load(Ordering::Relaxed)
     }
 
     /// Returns the device pixel ratio.
-    pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
+    pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
         let pc = match self.pres_context() {
             Some(pc) => pc,
-            None => return TypedScale::new(1.),
+            None => return Scale::new(1.),
         };
 
         let override_dppx = pc.mOverrideDPPX;
         if override_dppx > 0.0 {
-            return TypedScale::new(override_dppx);
+            return Scale::new(override_dppx);
         }
 
         let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
         let au_per_px = AU_PER_PX as f32;
-        TypedScale::new(au_per_px / au_per_dpx)
+        Scale::new(au_per_px / au_per_dpx)
     }
 
     /// Returns whether document colors are enabled.
     #[inline]
     pub fn use_document_colors(&self) -> bool {
         let doc = self.document();
         if doc.mIsBeingUsedAsImage() {
             return true;
--- a/servo/components/style/logical_geometry.rs
+++ b/servo/components/style/logical_geometry.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Geometry in flow-relative space.
 
 use crate::properties::style_structs;
 use euclid::num::Zero;
-use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
+use euclid::default::{Point2D, Rect, Size2D, SideOffsets2D};
 use std::cmp::{max, min};
 use std::fmt::{self, Debug, Error, Formatter};
 use std::ops::{Add, Sub};
 use unicode_bidi as bidi;
 
 pub enum BlockFlowDirection {
     TopToBottom,
     RightToLeft,
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -10,33 +10,33 @@ use crate::media_queries::media_feature:
 use crate::media_queries::media_feature_expression::RangeOrOperator;
 use crate::media_queries::MediaType;
 use crate::properties::ComputedValues;
 use crate::values::computed::font::FontSize;
 use crate::values::computed::CSSPixelLength;
 use crate::values::KeyframesName;
 use app_units::Au;
 use cssparser::RGBA;
-use euclid::{Size2D, TypedScale, TypedSize2D};
+use euclid::{Size2D, Scale, Size2D};
 use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
 use style_traits::viewport::ViewportConstraints;
 use style_traits::{CSSPixel, DevicePixel};
 
 /// A device is a structure that represents the current media a given document
 /// is displayed in.
 ///
 /// This is the struct against which media queries are evaluated.
 #[derive(Debug, MallocSizeOf)]
 pub struct Device {
     /// The current media type used by de device.
     media_type: MediaType,
     /// The current viewport size, in CSS pixels.
-    viewport_size: TypedSize2D<f32, CSSPixel>,
+    viewport_size: Size2D<f32, CSSPixel>,
     /// The current device pixel ratio, from CSS pixels to device pixels.
-    device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
+    device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
 
     /// The font size of the root element
     /// This is set when computing the style of the root
     /// element, and used for rem units in other elements
     ///
     /// When computing the style of the root element, there can't be any
     /// other style being computed at the same time, given we need the style of
     /// the parent to compute everything else. So it is correct to just use
@@ -54,18 +54,18 @@ pub struct Device {
     /// variables.
     environment: CssEnvironment,
 }
 
 impl Device {
     /// Trivially construct a new `Device`.
     pub fn new(
         media_type: MediaType,
-        viewport_size: TypedSize2D<f32, CSSPixel>,
-        device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
+        viewport_size: Size2D<f32, CSSPixel>,
+        device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
     ) -> Device {
         Device {
             media_type,
             viewport_size,
             device_pixel_ratio,
             // FIXME(bz): Seems dubious?
             root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
             used_root_font_size: AtomicBool::new(false),
@@ -135,17 +135,17 @@ impl Device {
     }
 
     /// Whether viewport units were used since the last device change.
     pub fn used_viewport_units(&self) -> bool {
         self.used_viewport_units.load(Ordering::Relaxed)
     }
 
     /// Returns the device pixel ratio.
-    pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
+    pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
         self.device_pixel_ratio
     }
 
     /// Take into account a viewport rule taken from the stylesheets.
     pub fn account_for_viewport_rule(&mut self, constraints: &ViewportConstraints) {
         self.viewport_size = constraints.size;
     }
 
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -20,17 +20,17 @@ use crate::stylesheets::{Origin, Stylesh
 use crate::values::computed::{Context, ToComputedValue};
 use crate::values::generics::length::LengthPercentageOrAuto;
 use crate::values::generics::NonNegative;
 use crate::values::specified::{self, NoCalcLength};
 use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength};
 use app_units::Au;
 use cssparser::CowRcStr;
 use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
-use euclid::TypedSize2D;
+use euclid::Size2D;
 use selectors::parser::SelectorParseErrorKind;
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::fmt::{self, Write};
 use std::iter::Enumerate;
 use std::str::Chars;
 use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
 use style_traits::{CssWriter, ParseError, PinchZoomFactor, StyleParseErrorKind, ToCss};
@@ -827,17 +827,17 @@ impl MaybeNew for ViewportConstraints {
             Au(0) => initial_viewport.height,
             initial_width => {
                 let ratio = initial_viewport.height.to_f32_px() / initial_width.to_f32_px();
                 Au::from_f32_px(width.to_f32_px() * ratio)
             },
         });
 
         Some(ViewportConstraints {
-            size: TypedSize2D::new(width.to_f32_px(), height.to_f32_px()),
+            size: Size2D::new(width.to_f32_px(), height.to_f32_px()),
 
             // TODO: compute a zoom factor for 'auto' as suggested by DEVICE-ADAPT ยง 10.
             initial_zoom: PinchZoomFactor::new(initial_zoom.unwrap_or(1.)),
             min_zoom: min_zoom.map(PinchZoomFactor::new),
             max_zoom: max_zoom.map(PinchZoomFactor::new),
 
             user_zoom: user_zoom,
             orientation: orientation,
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -18,17 +18,17 @@ use crate::font_metrics::{get_metrics_pr
 use crate::media_queries::Device;
 #[cfg(feature = "gecko")]
 use crate::properties;
 use crate::properties::{ComputedValues, LonghandId, StyleBuilder};
 use crate::rule_cache::RuleCacheConditions;
 use crate::Atom;
 #[cfg(feature = "servo")]
 use crate::Prefix;
-use euclid::Size2D;
+use euclid::default::Size2D;
 use std::cell::RefCell;
 use std::cmp;
 use std::f32;
 
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment};
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignSelf, JustifySelf};
--- a/servo/components/style/values/computed/transform.rs
+++ b/servo/components/style/values/computed/transform.rs
@@ -5,17 +5,17 @@
 //! Computed types for CSS values that are related to transformations.
 
 use super::CSSFloat;
 use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
 use crate::values::animated::ToAnimatedZero;
 use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
 use crate::values::generics::transform as generic;
 use crate::Zero;
-use euclid::{Transform3D, Vector3D};
+use euclid::default::{Transform3D, Vector3D};
 
 pub use crate::values::generics::transform::TransformStyle;
 
 /// A single operation in a computed CSS `transform`
 pub type TransformOperation =
     generic::GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>;
 /// A computed CSS `transform`
 pub type Transform = generic::GenericTransform<TransformOperation>;
--- a/servo/components/style/values/distance.rs
+++ b/servo/components/style/values/distance.rs
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Machinery to compute distances between animatable values.
 
 use app_units::Au;
-use euclid::Size2D;
+use euclid::default::Size2D;
 use std::iter::Sum;
 use std::ops::Add;
 
 /// A trait to compute squared distances between two animatable values.
 ///
 /// This trait is derivable with `#[derive(ComputeSquaredDistance)]`. The derived
 /// implementation uses a `match` expression with identical patterns for both
 /// `self` and `other`, calling `ComputeSquaredDistance::compute_squared_distance`
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -7,17 +7,18 @@
 use crate::values::computed::length::Length as ComputedLength;
 use crate::values::computed::length::LengthPercentage as ComputedLengthPercentage;
 use crate::values::specified::angle::Angle as SpecifiedAngle;
 use crate::values::specified::length::Length as SpecifiedLength;
 use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
 use crate::values::{computed, CSSFloat};
 use crate::Zero;
 use app_units::Au;
-use euclid::{self, Rect, Transform3D};
+use euclid::default::{Rect, Transform3D};
+use euclid;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ToCss};
 
 /// A generic 2D transformation matrix.
 #[allow(missing_docs)]
 #[derive(
     Clone,
     Copy,
@@ -557,17 +558,17 @@ impl<T: ToMatrix> Transform<T> {
         // Therefore, let's use Transform3D<f64> during matrix computation and cast it into f32
         // in the end.
         let mut transform = Transform3D::<f64>::identity();
         let mut contain_3d = false;
 
         for operation in &*self.0 {
             let matrix = operation.to_3d_matrix(reference_box)?;
             contain_3d |= operation.is_3d();
-            transform = transform.pre_mul(&matrix);
+            transform = transform.pre_transform(&matrix);
         }
 
         Ok((transform, contain_3d))
     }
 }
 
 /// Return the transform matrix from a perspective length.
 #[inline]
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -17,17 +17,17 @@ use crate::values::generics::length::{
 };
 use crate::values::generics::NonNegative;
 use crate::values::specified::calc::CalcNode;
 use crate::values::specified::NonNegativeNumber;
 use crate::values::CSSFloat;
 use crate::Zero;
 use app_units::Au;
 use cssparser::{Parser, Token};
-use euclid::Size2D;
+use euclid::default::Size2D;
 use std::cmp;
 use std::ops::{Add, Mul};
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{ParseError, SpecifiedValueInfo, StyleParseErrorKind};
 
 pub use super::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use super::image::{GradientKind, Image};
 pub use crate::values::specified::calc::CalcLengthPercentage;
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -12,17 +12,17 @@ path = "lib.rs"
 [features]
 servo = ["serde", "servo_atoms", "cssparser/serde", "webrender_api", "servo_url"]
 gecko = []
 
 [dependencies]
 app_units = "0.7"
 cssparser = "0.25"
 bitflags = "1.0"
-euclid = "0.19"
+euclid = "0.20"
 lazy_static = "1"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = "0.1"
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
 webrender_api = {git = "https://github.com/servo/webrender", optional = true}
 servo_atoms = {path = "../atoms", optional = true}
 servo_arc = { path = "../servo_arc" }
--- a/servo/components/style_traits/viewport.rs
+++ b/servo/components/style_traits/viewport.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Helper types for the `@viewport` rule.
 
 use crate::{CSSPixel, CssWriter, ParseError, PinchZoomFactor, ToCss};
 use cssparser::Parser;
-use euclid::TypedSize2D;
+use euclid::Size2D;
 use std::fmt::{self, Write};
 
 define_css_keyword_enum! {
     pub enum UserZoom {
         Zoom = "zoom",
         Fixed = "fixed",
     }
 }
@@ -28,17 +28,17 @@ define_css_keyword_enum! {
 ///
 /// <https://drafts.csswg.org/css-device-adapt/#viewport-desc>
 #[derive(Clone, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, MallocSizeOf))]
 pub struct ViewportConstraints {
     /// Width and height:
     ///  * https://drafts.csswg.org/css-device-adapt/#width-desc
     ///  * https://drafts.csswg.org/css-device-adapt/#height-desc
-    pub size: TypedSize2D<f32, CSSPixel>,
+    pub size: Size2D<f32, CSSPixel>,
     /// <https://drafts.csswg.org/css-device-adapt/#zoom-desc>
     pub initial_zoom: PinchZoomFactor,
     /// <https://drafts.csswg.org/css-device-adapt/#min-max-width-desc>
     pub min_zoom: Option<PinchZoomFactor>,
     /// <https://drafts.csswg.org/css-device-adapt/#min-max-width-desc>
     pub max_zoom: Option<PinchZoomFactor>,
     /// <https://drafts.csswg.org/css-device-adapt/#user-zoom-desc>
     pub user_zoom: UserZoom,
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -8,17 +8,17 @@ license = "MPL-2.0"
 name = "style_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
 byteorder = "1.0"
 app_units = "0.7"
 cssparser = "0.25"
-euclid = "0.19"
+euclid = "0.20"
 html5ever = "0.22"
 parking_lot = "0.8"
 rayon = "1"
 serde_json = "1.0"
 selectors = {path = "../../../components/selectors"}
 servo_arc = {path = "../../../components/servo_arc"}
 servo_atoms = {path = "../../../components/atoms"}
 servo_config = {path = "../../../components/config"}
--- a/servo/tests/unit/style/media_queries.rs
+++ b/servo/tests/unit/style/media_queries.rs
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
-use euclid::TypedScale;
-use euclid::TypedSize2D;
+use euclid::Scale;
+use euclid::Size2D;
 use servo_arc::Arc;
 use servo_url::ServoUrl;
 use std::borrow::ToOwned;
 use style::Atom;
 use style::context::QuirksMode;
 use style::media_queries::*;
 use style::servo::media_queries::*;
 use style::shared_lock::SharedRwLock;
@@ -22,17 +22,17 @@ where
 {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let css_str = css.to_owned();
     let lock = SharedRwLock::new();
     let media_list = Arc::new(lock.wrap(MediaList::empty()));
     let stylesheet = Stylesheet::from_str(
         css, url, Origin::Author, media_list, lock,
         None, None, QuirksMode::NoQuirks, 0);
-    let dummy = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
+    let dummy = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
     let mut rule_count = 0;
     let guard = stylesheet.shared_lock.read();
     for rule in stylesheet.iter_rules::<AllRules>(&dummy, &guard) {
         if let CssRule::Media(ref lock) = *rule {
             rule_count += 1;
             callback(&lock.read_with(&guard).media_queries.read_with(&guard), css);
         }
     }
@@ -328,33 +328,33 @@ fn test_mq_malformed_expressions() {
         "@media , {}",
     ] {
         test_media_rule(rule, check_malformed_expr);
     }
 }
 
 #[test]
 fn test_matching_simple() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
 
     media_query_test(&device, "@media not all { a { color: red; } }", 0);
     media_query_test(&device, "@media not screen { a { color: red; } }", 0);
     media_query_test(&device, "@media not print { a { color: red; } }", 1);
 
     media_query_test(&device, "@media unknown { a { color: red; } }", 0);
     media_query_test(&device, "@media not unknown { a { color: red; } }", 1);
 
     media_query_test(&device, "@media { a { color: red; } }", 1);
     media_query_test(&device, "@media screen { a { color: red; } }", 1);
     media_query_test(&device, "@media print { a { color: red; } }", 0);
 }
 
 #[test]
 fn test_matching_width() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
 
     media_query_test(&device, "@media { a { color: red; } }", 1);
 
     media_query_test(&device, "@media (min-width: 50px) { a { color: red; } }", 1);
     media_query_test(&device, "@media (min-width: 150px) { a { color: red; } }", 1);
     media_query_test(&device, "@media (min-width: 300px) { a { color: red; } }", 0);
 
     media_query_test(&device, "@media screen and (min-width: 50px) { a { color: red; } }", 1);
@@ -385,14 +385,14 @@ fn test_matching_width() {
     media_query_test(
         &device, "@media not screen and (min-width: 16em) and (max-width: 19.75em) { a { color: red; } }", 1);
     media_query_test(
         &device, "@media not screen and (min-width: 3em) and (max-width: 250px) { a { color: red; } }", 0);
 }
 
 #[test]
 fn test_matching_invalid() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
 
     media_query_test(&device, "@media fridge { a { color: red; } }", 0);
     media_query_test(&device, "@media screen and (height: 100px) { a { color: red; } }", 0);
     media_query_test(&device, "@media not print and (width: 100) { a { color: red; } }", 0);
 }
--- a/servo/tests/unit/style/stylist.rs
+++ b/servo/tests/unit/style/stylist.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 use cssparser::SourceLocation;
-use euclid::TypedScale;
-use euclid::TypedSize2D;
+use euclid::Scale;
+use euclid::Size2D;
 use selectors::parser::{AncestorHashes, Selector};
 use servo_arc::Arc;
 use servo_atoms::Atom;
 use style::context::QuirksMode;
 use style::media_queries::{Device, MediaType};
 use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
 use style::properties::{longhands, Importance};
 use style::selector_map::SelectorMap;
@@ -174,17 +174,17 @@ fn test_insert() {
     assert_eq!(1, selector_map.id_hash.get(&Atom::from("top"), QuirksMode::NoQuirks).unwrap()[0].source_order);
     selector_map.insert(rules_list[0][0].clone(), QuirksMode::NoQuirks)
                 .expect("OOM");
     assert_eq!(0, selector_map.class_hash.get(&Atom::from("foo"), QuirksMode::NoQuirks).unwrap()[0].source_order);
     assert!(selector_map.class_hash.get(&Atom::from("intro"), QuirksMode::NoQuirks).is_none());
 }
 
 fn mock_stylist() -> Stylist {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(0f32, 0f32), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(0f32, 0f32), Scale::new(1.0));
     Stylist::new(device, QuirksMode::NoQuirks)
 }
 
 #[test]
 fn test_stylist_device_accessors() {
     thread_state::initialize(ThreadState::LAYOUT);
     let stylist = mock_stylist();
     assert_eq!(stylist.device().media_type(), MediaType::screen());
--- a/servo/tests/unit/style/viewport.rs
+++ b/servo/tests/unit/style/viewport.rs
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 use cssparser::{Parser, ParserInput};
-use euclid::TypedScale;
-use euclid::TypedSize2D;
+use euclid::Scale;
+use euclid::Size2D;
 use servo_arc::Arc;
 use servo_config::prefs::{PREFS, PrefValue};
 use servo_url::ServoUrl;
 use style::context::QuirksMode;
 use style::media_queries::{Device, MediaList, MediaType};
 use style::parser::ParserContext;
 use style::shared_lock::{SharedRwLock, StylesheetGuards};
 use style::stylesheets::{CssRuleType, Stylesheet, StylesheetInDocument, Origin};
@@ -91,17 +91,17 @@ macro_rules! viewport_length {
     };
     ($value:expr, vw) => {
         ViewportLength::Specified(LengthPercentageOrAuto::Length(ViewportPercentage(Vw($value))))
     }
 }
 
 #[test]
 fn empty_viewport_rule() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
 
     test_viewport_rule("@viewport {}", &device, |declarations, css| {
         println!("{}", css);
         assert_decl_len!(declarations == 0);
     });
 }
 
 macro_rules! assert_decl_eq {
@@ -114,17 +114,17 @@ macro_rules! assert_decl_eq {
         assert_eq!($d.origin, Origin::$origin);
         assert_eq!($d.descriptor, ViewportDescriptor::$expected($value));
         assert_eq!($d.important, true, "descriptor should be !important");
     }};
 }
 
 #[test]
 fn simple_viewport_rules() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
 
     test_viewport_rule("@viewport { width: auto; height: auto;\
                                     zoom: auto; min-zoom: 0; max-zoom: 200%;\
                                     user-zoom: zoom; orientation: auto; }",
                        &device, |declarations, css| {
         println!("{}", css);
         assert_decl_len!(declarations == 9);
         assert_decl_eq!(&declarations[0], Author, MinWidth: ViewportLength::Specified(Auto));
@@ -186,17 +186,17 @@ fn simple_meta_viewport_contents() {
         assert_decl_eq!(&declarations[1], Author, MaxWidth: viewport_length!(480., px));
         assert_decl_eq!(&declarations[2], Author, Zoom: Zoom::Number(2.));
         assert_decl_eq!(&declarations[3], Author, UserZoom: UserZoom::Zoom);
     });
 }
 
 #[test]
 fn cascading_within_viewport_rule() {
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
 
     // normal order of appearance
     test_viewport_rule("@viewport { min-width: 200px; min-width: auto; }",
                        &device, |declarations, css| {
         println!("{}", css);
         assert_decl_len!(declarations == 1);
         assert_decl_eq!(&declarations[0], Author, MinWidth: ViewportLength::Specified(Auto));
     });
@@ -252,17 +252,17 @@ fn cascading_within_viewport_rule() {
         assert_decl_eq!(&declarations[0], Author, MinWidth: ViewportLength::Specified(Auto), !important);
         assert_decl_eq!(&declarations[1], Author, MaxWidth: ViewportLength::Specified(Auto), !important);
     });
 }
 
 #[test]
 fn multiple_stylesheets_cascading() {
     PREFS.set("layout.viewport.enabled", PrefValue::Boolean(true));
-    let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
+    let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
     let shared_lock = SharedRwLock::new();
     let stylesheets = vec![
         stylesheet!("@viewport { min-width: 100px; min-height: 100px; zoom: 1; }",
                     UserAgent,
                     shared_lock.clone()),
         stylesheet!("@viewport { min-width: 200px; min-height: 200px; }",
                     User, shared_lock.clone()),
         stylesheet!("@viewport { min-width: 300px; }",
@@ -312,18 +312,18 @@ fn constrain_viewport() {
     );
 
     macro_rules! from_css {
         ($css:expr) => {
             &ViewportRule::parse(&context, &mut Parser::new(&mut $css)).unwrap()
         }
     }
 
-    let initial_viewport = TypedSize2D::new(800., 600.);
-    let device = Device::new(MediaType::screen(), initial_viewport, TypedScale::new(1.0));
+    let initial_viewport = Size2D::new(800., 600.);
+    let device = Device::new(MediaType::screen(), initial_viewport, Scale::new(1.0));
     let mut input = ParserInput::new("");
     assert_eq!(ViewportConstraints::maybe_new(&device, from_css!(input), QuirksMode::NoQuirks), None);
 
     let mut input = ParserInput::new("width: 320px auto");
     assert_eq!(ViewportConstraints::maybe_new(&device, from_css!(input), QuirksMode::NoQuirks),
                Some(ViewportConstraints {
                    size: initial_viewport,
 
@@ -361,22 +361,22 @@ fn constrain_viewport() {
                    initial_zoom: PinchZoomFactor::new(1.),
                    min_zoom: None,
                    max_zoom: None,
 
                    user_zoom: UserZoom::Zoom,
                    orientation: Orientation::Auto
                }));
 
-    let initial_viewport = TypedSize2D::new(200., 150.);
-    let device = Device::new(MediaType::screen(), initial_viewport, TypedScale::new(1.0));
+    let initial_viewport = Size2D::new(200., 150.);
+    let device = Device::new(MediaType::screen(), initial_viewport, Scale::new(1.0));
     let mut input = ParserInput::new("width: 320px auto");
     assert_eq!(ViewportConstraints::maybe_new(&device, from_css!(input), QuirksMode::NoQuirks),
                Some(ViewportConstraints {
-                   size: TypedSize2D::new(320., 240.),
+                   size: Size2D::new(320., 240.),
 
                    initial_zoom: PinchZoomFactor::new(1.),
                    min_zoom: None,
                    max_zoom: None,
 
                    user_zoom: UserZoom::Zoom,
                    orientation: Orientation::Auto
                }));
--- a/third_party/rust/euclid/.cargo-checksum.json
+++ b/third_party/rust/euclid/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"6ed8512d0e0c349a53eddd15a806e67e84359c1071d7d4a404f513cca091d5f5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"5e2d634cf2181fd9f556a600d4339cb6a098341ac71f72e0bc7521b3b3fb2f19","src/box3d.rs":"8d87e7e487d0772462cc2c6033bcd05f4fee44127c4aa0a4d72407ac6a02e03b","src/homogen.rs":"7b02aa671fffcb554557ad790f598bd5d7440dc1aa4a6d1c5a97d8bc3c8f64d6","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"e8bbae14e1b284fba3529af44396e488cbc48f8b3d20ddb26da5919d9c02601b","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b51cf9b7713d9a48452d833cfbc97bb95e0c2202c4f77cadd02633ce80a600df","src/rect.rs":"2e4036f3f7e2ca62e6f9a52787ca9b9765b401a11cf1e70dff6c81142bdd91ed","src/rigid.rs":"e50a5df42add328ed5164e1954592406ce6d8f564beb4ca375c5cca920e93fbc","src/rotation.rs":"3d1a934a7c59bd7ca8501d17d463d5af41fb529c5aa8fe8c3bb8a2b236d4abc0","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"d9b1463672e1204bf8e7dd6fe0f7601eb75b6690ec6eb18debcee07f5ca92ee3","src/size.rs":"c4e38966c280ab5b4963961eebdbb12e0f448aea624cbe760b02ca2221a004e5","src/transform2d.rs":"7657d447993dc820e404ea9fbde6cb2900d874d4f5c735e85c6225c9f3b4110d","src/transform3d.rs":"af3d909ee103d02fec5f59599055cc3cee5217975b030e0089e1f1d99ad5139e","src/translation.rs":"b21d1d81a34b80d3285d42f33e8039fdb787749f017d2a7a2295d036c2f50548","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"dcd0904757ed0e7d12da1c612746da3e32c56e2248ec13041d1f3786811af51c"},"package":"596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"}
\ No newline at end of file
+{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7ae5531c88ac476361c06e6ee5531839eff3b301c66ba05619570b3ab7926467","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"0dc013b9bfe088e62df8675674a5430580ecfaff202d0966ba5d316e7ff0165e","src/box3d.rs":"f15962fa34ef4dec099ca7403651ac92d5be55eba7aee0300b1a2837643dcb86","src/homogen.rs":"5c14355182b4fb7c148fc65c1f63b25607019ae8d763e187d659925e2ca210a3","src/length.rs":"b1f44beb961b193bea814f5a15aee713cab97d076de13e51e294891fd7153f27","src/lib.rs":"d58eecf5847b37f68ac6604c5b5a16962756faf04f9af1f5293228486b120378","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/nonempty.rs":"865d51dc1ae785ee2e6e94eb2ee935f29a86b9efa8daa322bca7992fa9ae70fc","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b0eeed9f99cdd81525dd32b4d76caff862447e129b29bf55d003a35425e93ab6","src/rect.rs":"8298e2b67c7aadd255a53d42a6e5b19968aa47fcff05f8c60f4073da0a808dfc","src/rigid.rs":"aab59591562938695e63487230504b2d94df6e3a7b7740069166c8499d4fa930","src/rotation.rs":"307b22df279f30e4ac4aa35a0d69fb7f9196bd553c06b7f519692655e1e353d3","src/scale.rs":"6a4c3da9444c72e967d5217bbe5442a8517448857cb32472f883d6da58b8f846","src/side_offsets.rs":"eaa52aa64f0fa041fbd5c1c9165a01614db6c37d4746a56c3294a388bd5e0616","src/size.rs":"b3478be99f4409d3083e7553f5906c8ac314beddb83cc87492415c02785b8311","src/transform2d.rs":"8a0b4f097c8e98408dfe709b3ef0e8530562a6e1b68f62d6cd86c906cc0bb7eb","src/transform3d.rs":"6a6d56b67fdb1b6d4bfd725959d6b95cf4fa5ffbc272ae9f1508a400a3a4b30e","src/translation.rs":"67afb126179e3cb5a2c1bd462a8f5c87630233a68f63ff6a2194dbd3b229d734","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"ca39c30729f781dd5e64b5fea1516e676b6ab4fc57788895fa2ca5309ad73ec3"},"package":"2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"}
\ No newline at end of file
--- a/third_party/rust/euclid/Cargo.toml
+++ b/third_party/rust/euclid/Cargo.toml
@@ -7,38 +7,32 @@
 #
 # 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.9"
+version = "0.20.0"
 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.euclid_macros]
-version = "0.1"
-
 [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 = []
--- a/third_party/rust/euclid/src/box2d.rs
+++ b/third_party/rust/euclid/src/box2d.rs
@@ -3,23 +3,24 @@
 //
 // 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 scale::TypedScale;
+use scale::Scale;
 use num::*;
-use rect::TypedRect;
-use point::{point2, TypedPoint2D};
-use vector::{vec2, TypedVector2D};
-use side_offsets::TypedSideOffsets2D;
-use size::TypedSize2D;
+use rect::Rect;
+use point::{point2, Point2D};
+use vector::{vec2, Vector2D};
+use side_offsets::SideOffsets2D;
+use size::Size2D;
+use nonempty::NonEmpty;
 use approxord::{min, max};
 
 use num_traits::NumCast;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
 use core::borrow::Borrow;
 use core::cmp::PartialOrd;
@@ -27,83 +28,80 @@ use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::ops::{Add, Div, Mul, Sub};
 
 
 /// An axis aligned rectangle represented by its minimum and maximum coordinates.
 #[repr(C)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
-pub struct TypedBox2D<T, U> {
-    pub min: TypedPoint2D<T, U>,
-    pub max: TypedPoint2D<T, U>,
+pub struct Box2D<T, U> {
+    pub min: Point2D<T, U>,
+    pub max: Point2D<T, U>,
 }
 
-/// The default box 2d type with no unit.
-pub type Box2D<T> = TypedBox2D<T, UnknownUnit>;
-
-impl<T: Hash, U> Hash for TypedBox2D<T, U> {
+impl<T: Hash, U> Hash for Box2D<T, U> {
     fn hash<H: Hasher>(&self, h: &mut H) {
         self.min.hash(h);
         self.max.hash(h);
     }
 }
 
-impl<T: Copy, U> Copy for TypedBox2D<T, U> {}
+impl<T: Copy, U> Copy for Box2D<T, U> {}
 
-impl<T: Copy, U> Clone for TypedBox2D<T, U> {
+impl<T: Copy, U> Clone for Box2D<T, U> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-impl<T: PartialEq, U> PartialEq<TypedBox2D<T, U>> for TypedBox2D<T, U> {
+impl<T: PartialEq, U> PartialEq<Box2D<T, U>> for Box2D<T, U> {
     fn eq(&self, other: &Self) -> bool {
         self.min.eq(&other.min) && self.max.eq(&other.max)
     }
 }
 
-impl<T: Eq, U> Eq for TypedBox2D<T, U> {}
+impl<T: Eq, U> Eq for Box2D<T, U> {}
 
-impl<T: fmt::Debug, U> fmt::Debug for TypedBox2D<T, U> {
+impl<T: fmt::Debug, U> fmt::Debug for Box2D<T, U> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypedBox2D({:?}, {:?})", self.min, self.max)
+        write!(f, "Box2D({:?}, {:?})", self.min, self.max)
     }
 }
 
-impl<T: fmt::Display, U> fmt::Display for TypedBox2D<T, U> {
+impl<T: fmt::Display, U> fmt::Display for Box2D<T, U> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "Box2D({}, {})", self.min, self.max)
     }
 }
 
-impl<T, U> TypedBox2D<T, U> {
+impl<T, U> Box2D<T, U> {
     /// Constructor.
-    pub fn new(min: TypedPoint2D<T, U>, max: TypedPoint2D<T, U>) -> Self {
-        TypedBox2D {
+    pub fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
+        Box2D {
             min,
             max,
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Zero + PartialOrd,
 {
     /// Creates a Box2D of the given size, at offset zero.
     #[inline]
-    pub fn from_size(size: TypedSize2D<T, U>) -> Self {
-        let zero = TypedPoint2D::zero();
+    pub fn from_size(size: Size2D<T, U>) -> Self {
+        let zero = Point2D::zero();
         let point = size.to_vector().to_point();
-        TypedBox2D::from_points(&[zero, point])
+        Box2D::from_points(&[zero, point])
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + PartialOrd,
 {
     /// Returns true if the box has a negative area.
     ///
     /// The common interpretation for a negative box is to consider it empty. It can be obtained
     /// by calculating the intersection of two boxes that do not intersect.
     #[inline]
@@ -112,171 +110,183 @@ where
     }
 
     /// Returns true if the size is zero or negative.
     #[inline]
     pub fn is_empty_or_negative(&self) -> bool {
         self.max.x <= self.min.x || self.max.y <= self.min.y
     }
 
+    #[inline]
+    pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
+        if self.is_empty_or_negative() {
+            return None;
+        }
+
+        Some(NonEmpty(*self))
+    }
+
     /// Returns true if the two boxes intersect.
     #[inline]
     pub fn intersects(&self, other: &Self) -> bool {
         self.min.x < other.max.x
             && self.max.x > other.min.x
             && self.min.y < other.max.y
             && self.max.y > other.min.y
     }
 
     /// Computes the intersection of two boxes.
     ///
     /// The result is a negative box if the boxes do not intersect.
     #[inline]
     pub fn intersection(&self, other: &Self) -> Self {
-        TypedBox2D {
+        Box2D {
             min: point2(
                 max(self.min.x, other.min.x),
                 max(self.min.y, other.min.y),
             ),
             max: point2(
                 min(self.max.x, other.max.x),
                 min(self.max.y, other.max.y),
             )
         }
     }
 
     /// Computes the intersection of two boxes, returning `None` if the boxes do not intersect.
     #[inline]
-    pub fn try_intersection(&self, other: &Self) -> Option<Self> {
+    pub fn try_intersection(&self, other: &Self) -> Option<NonEmpty<Self>> {
         let intersection = self.intersection(other);
 
         if intersection.is_negative() {
             return None;
         }
 
-        Some(intersection)
+        Some(NonEmpty(intersection))
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Add<T, Output = T>,
 {
     /// Returns the same box, translated by a vector.
     #[inline]
-    pub fn translate(&self, by: &TypedVector2D<T, U>) -> Self {
-        Self::new(self.min + *by, self.max + *by)
+    pub fn translate(&self, by: Vector2D<T, U>) -> Self {
+        Box2D {
+            min: self.min + by,
+            max: self.max + by,
+        }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + PartialOrd + Zero,
 {
     /// Returns true if this box contains the point. Points are considered
     /// in the box if they are on the front, left or top faces, but outside if they
     /// are on the back, right or bottom faces.
     #[inline]
-    pub fn contains(&self, p: &TypedPoint2D<T, U>) -> bool {
+    pub fn contains(&self, p: Point2D<T, U>) -> bool {
         self.min.x <= p.x && p.x < self.max.x
             && self.min.y <= p.y && p.y < self.max.y
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
 {
     /// Returns true if this box contains the interior of the other box. Always
     /// returns true if other is empty, and always returns false if other is
     /// nonempty but this box is empty.
     #[inline]
     pub fn contains_box(&self, other: &Self) -> bool {
         other.is_empty_or_negative()
             || (self.min.x <= other.min.x && other.max.x <= self.max.x
                 && self.min.y <= other.min.y && other.max.y <= self.max.y)
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Sub<T, Output = T>,
 {
     #[inline]
-    pub fn size(&self)-> TypedSize2D<T, U> {
+    pub fn size(&self)-> Size2D<T, U> {
         (self.max - self.min).to_size()
     }
 
     #[inline]
-    pub fn to_rect(&self) -> TypedRect<T, U> {
-        TypedRect {
+    pub fn to_rect(&self) -> Rect<T, U> {
+        Rect {
             origin: self.min,
             size: self.size(),
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
 {
     /// Inflates the box by the specified sizes on each side respectively.
     #[inline]
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn inflate(&self, width: T, height: T) -> Self {
-        TypedBox2D {
+        Box2D {
             min: point2(self.min.x - width, self.min.y - height),
             max: point2(self.max.x + width, self.max.y + height),
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Zero + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
 {
     /// Calculate the size and position of an inner box.
     ///
     /// Subtracts the side offsets from all sides. The horizontal, vertical
     /// and applicate offsets must not be larger than the original side length.
-    pub fn inner_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
-        TypedBox2D {
+    pub fn inner_box(&self, offsets: SideOffsets2D<T, U>) -> Self {
+        Box2D {
             min: self.min + vec2(offsets.left, offsets.top),
             max: self.max - vec2(offsets.right, offsets.bottom),
         }
     }
 
     /// Calculate the b and position of an outer box.
     ///
     /// Add the offsets to all sides. The expanded box is returned.
-    pub fn outer_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
-        TypedBox2D {
+    pub fn outer_box(&self, offsets: SideOffsets2D<T, U>) -> Self {
+        Box2D {
             min: self.min - vec2(offsets.left, offsets.top),
             max: self.max + vec2(offsets.right, offsets.bottom),
         }
     }
 }
 
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Zero + PartialOrd,
 {
     /// Returns the smallest box containing all of the provided points.
     pub fn from_points<I>(points: I) -> Self
     where
         I: IntoIterator,
-        I::Item: Borrow<TypedPoint2D<T, U>>,
+        I::Item: Borrow<Point2D<T, U>>,
     {
         let mut points = points.into_iter();
 
         // Need at least 2 different points for a valid box (ie: volume > 0).
         let (mut min_x, mut min_y) = match points.next() {
             Some(first) => (first.borrow().x, first.borrow().y),
-            None => return TypedBox2D::zero(),
+            None => return Box2D::zero(),
         };
         let (mut max_x, mut max_y) = (min_x, min_y);
 
         {
             let mut assign_min_max = |point: I::Item| {
                 let p = point.borrow();
                 if p.x < min_x {
                     min_x = p.x
@@ -289,321 +299,321 @@ where
                 }
                 if p.y > max_y {
                     max_y = p.y
                 }
             };
 
             match points.next() {
                 Some(second) => assign_min_max(second),
-                None => return TypedBox2D::zero(),
+                None => return Box2D::zero(),
             }
 
             for point in points {
                 assign_min_max(point);
             }
         }
 
-        TypedBox2D {
+        Box2D {
             min: point2(min_x, min_y),
             max: point2(max_x, max_y),
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
 {
     /// Linearly interpolate between this box and another box.
     ///
     /// `t` is expected to be between zero and one.
     #[inline]
     pub fn lerp(&self, other: Self, t: T) -> Self {
         Self::new(
             self.min.lerp(other.min, t),
             self.max.lerp(other.max, t),
         )
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + One + Add<Output = T> + Div<Output = T>,
 {
-    pub fn center(&self) -> TypedPoint2D<T, U> {
+    pub fn center(&self) -> Point2D<T, U> {
         let two = T::one() + T::one();
         (self.min + self.max.to_vector()) / two
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + PartialOrd,
 {
     #[inline]
     pub fn union(&self, other: &Self) -> Self {
-        TypedBox2D {
+        Box2D {
             min: point2(
                 min(self.min.x, other.min.x),
                 min(self.min.y, other.min.y),
             ),
             max: point2(
                 max(self.max.x, other.max.x),
                 max(self.max.y, other.max.y),
             ),
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy,
 {
     #[inline]
     pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
     where
         T: Mul<S, Output = T>
     {
-        TypedBox2D {
+        Box2D {
             min: point2(self.min.x * x, self.min.y * y),
             max: point2(self.max.x * x, self.max.y * y),
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
 {
     #[inline]
     pub fn area(&self) -> T {
         let size = self.size();
         size.width * size.height
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Copy + Zero,
 {
     /// Constructor, setting all sides to zero.
     pub fn zero() -> Self {
-        TypedBox2D::new(TypedPoint2D::zero(), TypedPoint2D::zero())
+        Box2D::new(Point2D::zero(), Point2D::zero())
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: PartialEq,
 {
     /// Returns true if the size is zero.
     #[inline]
     pub fn is_empty(&self) -> bool {
         self.min.x == self.max.x || self.min.y == self.max.y
     }
 }
 
-impl<T, U> Mul<T> for TypedBox2D<T, U>
+impl<T, U> Mul<T> for Box2D<T, U>
 where
     T: Copy + Mul<T, Output = T>,
 {
     type Output = Self;
     #[inline]
     fn mul(self, scale: T) -> Self {
-        TypedBox2D::new(self.min * scale, self.max * scale)
+        Box2D::new(self.min * scale, self.max * scale)
     }
 }
 
-impl<T, U> Div<T> for TypedBox2D<T, U>
+impl<T, U> Div<T> for Box2D<T, U>
 where
     T: Copy + Div<T, Output = T>,
 {
     type Output = Self;
     #[inline]
     fn div(self, scale: T) -> Self {
-        TypedBox2D::new(self.min / scale, self.max / scale)
+        Box2D::new(self.min / scale, self.max / scale)
     }
 }
 
-impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox2D<T, U1>
+impl<T, U1, U2> Mul<Scale<T, U1, U2>> for Box2D<T, U1>
 where
     T: Copy + Mul<T, Output = T>,
 {
-    type Output = TypedBox2D<T, U2>;
+    type Output = Box2D<T, U2>;
     #[inline]
-    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U2> {
-        TypedBox2D::new(self.min * scale, self.max * scale)
+    fn mul(self, scale: Scale<T, U1, U2>) -> Box2D<T, U2> {
+        Box2D::new(self.min * scale, self.max * scale)
     }
 }
 
-impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox2D<T, U2>
+impl<T, U1, U2> Div<Scale<T, U1, U2>> for Box2D<T, U2>
 where
     T: Copy + Div<T, Output = T>,
 {
-    type Output = TypedBox2D<T, U1>;
+    type Output = Box2D<T, U1>;
     #[inline]
-    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U1> {
-        TypedBox2D::new(self.min / scale, self.max / scale)
+    fn div(self, scale: Scale<T, U1, U2>) -> Box2D<T, U1> {
+        Box2D::new(self.min / scale, self.max / scale)
     }
 }
 
-impl<T, Unit> TypedBox2D<T, Unit>
+impl<T, Unit> Box2D<T, Unit>
 where
     T: Copy,
 {
     /// Drop the units, preserving only the numeric value.
-    pub fn to_untyped(&self) -> Box2D<T> {
-        TypedBox2D::new(self.min.to_untyped(), self.max.to_untyped())
+    pub fn to_untyped(&self) -> Box2D<T, UnknownUnit> {
+        Box2D::new(self.min.to_untyped(), self.max.to_untyped())
     }
 
     /// Tag a unitless value with units.
-    pub fn from_untyped(c: &Box2D<T>) -> TypedBox2D<T, Unit> {
-        TypedBox2D::new(
-            TypedPoint2D::from_untyped(&c.min),
-            TypedPoint2D::from_untyped(&c.max),
+    pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, Unit> {
+        Box2D::new(
+            Point2D::from_untyped(c.min),
+            Point2D::from_untyped(c.max),
         )
     }
 }
 
-impl<T0, Unit> TypedBox2D<T0, Unit>
+impl<T0, Unit> Box2D<T0, Unit>
 where
     T0: NumCast + Copy,
 {
     /// 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) -> TypedBox2D<T1, Unit> {
-        TypedBox2D::new(
+    pub fn cast<T1: NumCast + Copy>(&self) -> Box2D<T1, Unit> {
+        Box2D::new(
             self.min.cast(),
             self.max.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<TypedBox2D<T1, Unit>> {
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box2D<T1, Unit>> {
         match (self.min.try_cast(), self.max.try_cast()) {
-            (Some(a), Some(b)) => Some(TypedBox2D::new(a, b)),
+            (Some(a), Some(b)) => Some(Box2D::new(a, b)),
             _ => None,
         }
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Round,
 {
     /// Return a box with edges rounded to integer coordinates, such that
     /// the returned box has the same set of pixel centers as the original
     /// one.
     /// Values equal to 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)]
+    #[must_use]
     pub fn round(&self) -> Self {
-        TypedBox2D::new(self.min.round(), self.max.round())
+        Box2D::new(self.min.round(), self.max.round())
     }
 }
 
-impl<T, U> TypedBox2D<T, U>
+impl<T, U> Box2D<T, U>
 where
     T: Floor + Ceil,
 {
     /// Return a box with faces/edges rounded to integer coordinates, such that
     /// the original box contains the resulting box.
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn round_in(&self) -> Self {
         let min = self.min.ceil();
         let max = self.max.floor();
-        TypedBox2D { min, max }
+        Box2D { min, max }
     }
 
     /// Return a box with faces/edges rounded to integer coordinates, such that
     /// the original box is contained in the resulting box.
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn round_out(&self) -> Self {
         let min = self.min.floor();
         let max = self.max.ceil();
-        TypedBox2D { min, max }
+        Box2D { min, max }
     }
 }
 
 // Convenience functions for common casts
-impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
+impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
     /// Cast into an `f32` box.
-    pub fn to_f32(&self) -> TypedBox2D<f32, Unit> {
+    pub fn to_f32(&self) -> Box2D<f32, Unit> {
         self.cast()
     }
 
     /// Cast into an `f64` box.
-    pub fn to_f64(&self) -> TypedBox2D<f64, Unit> {
+    pub fn to_f64(&self) -> Box2D<f64, Unit> {
         self.cast()
     }
 
     /// Cast into an `usize` box, truncating decimals if any.
     ///
     /// When casting from floating point boxes, 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) -> TypedBox2D<usize, Unit> {
+    pub fn to_usize(&self) -> Box2D<usize, Unit> {
         self.cast()
     }
 
     /// Cast into an `u32` box, truncating decimals if any.
     ///
     /// When casting from floating point boxes, 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) -> TypedBox2D<u32, Unit> {
+    pub fn to_u32(&self) -> Box2D<u32, Unit> {
         self.cast()
     }
 
     /// Cast into an `i32` box, truncating decimals if any.
     ///
     /// When casting from floating point boxes, 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) -> TypedBox2D<i32, Unit> {
+    pub fn to_i32(&self) -> Box2D<i32, Unit> {
         self.cast()
     }
 
     /// Cast into an `i64` box, truncating decimals if any.
     ///
     /// When casting from floating point boxes, 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) -> TypedBox2D<i64, Unit> {
+    pub fn to_i64(&self) -> Box2D<i64, Unit> {
         self.cast()
     }
 }
 
-impl<T, U> From<TypedSize2D<T, U>> for TypedBox2D<T, U>
+impl<T, U> From<Size2D<T, U>> for Box2D<T, U>
 where
     T: Copy + Zero + PartialOrd,
 {
-    fn from(b: TypedSize2D<T, U>) -> Self {
+    fn from(b: Size2D<T, U>) -> Self {
         Self::from_size(b)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use side_offsets::SideOffsets2D;
-    use size::size2;
-    use point::Point2D;
-    use super::*;
+    use {Point2D, point2, vec2, size2};
+    use default::Box2D;
+    //use super::*;
 
     #[test]
     fn test_size() {
         let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
         assert_eq!(b.size().width, 20.0);
         assert_eq!(b.size().height, 20.0);
     }
 
@@ -683,17 +693,17 @@ mod tests {
 
     #[test]
     fn test_translate() {
         let size = size2(15.0, 15.0);
         let mut center = (size / 2.0).to_vector().to_point();
         let b = Box2D::from_size(size);
         assert_eq!(b.center(), center);
         let translation = vec2(10.0, 2.5);
-        let b = b.translate(&translation);
+        let b = b.translate(translation);
         center += translation;
         assert_eq!(b.center(), center);
         assert_eq!(b.max.x, 25.0);
         assert_eq!(b.max.y, 17.5);
         assert_eq!(b.min.x, 10.0);
         assert_eq!(b.min.y, 2.5);
     }
 
@@ -755,17 +765,17 @@ mod tests {
         assert_eq!(b.center(), Point2D::zero());
         assert_eq!(b.size().width, 10.0);
         assert_eq!(b.size().height, 10.0);
     }
 
     #[test]
     fn test_contains() {
         let b = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
-        assert!(b.contains(&point2(-15.3, 10.5)));
+        assert!(b.contains(point2(-15.3, 10.5)));
     }
 
     #[test]
     fn test_contains_box() {
         let b1 = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
         let b2 = Box2D::from_points(&[point2(-14.3, -16.5), point2(6.7, 17.6)]);
         assert!(b1.contains_box(&b2));
     }
--- a/third_party/rust/euclid/src/box3d.rs
+++ b/third_party/rust/euclid/src/box3d.rs
@@ -3,106 +3,103 @@
 //
 // 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 scale::Scale;
 use num::*;
-use point::TypedPoint3D;
-use vector::TypedVector3D;
-use size::TypedSize3D;
+use point::Point3D;
+use vector::Vector3D;
+use size::Size3D;
 use approxord::{min, max};
+use nonempty::NonEmpty;
 
 use num_traits::NumCast;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
 use core::borrow::Borrow;
 use core::cmp::PartialOrd;
 use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::ops::{Add, Div, Mul, Sub};
 
 
 /// An axis aligned 3D box represented by its minimum and maximum coordinates.
 #[repr(C)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
-pub struct TypedBox3D<T, U> {
-    pub min: TypedPoint3D<T, U>, 
-    pub max: TypedPoint3D<T, U>,
+pub struct Box3D<T, U> {
+    pub min: Point3D<T, U>, 
+    pub max: Point3D<T, U>,
 }
 
-/// The default box 3d type with no unit.
-pub type Box3D<T> = TypedBox3D<T, UnknownUnit>;
-
-impl<T: Hash, U> Hash for TypedBox3D<T, U> {
+impl<T: Hash, U> Hash for Box3D<T, U> {
     fn hash<H: Hasher>(&self, h: &mut H) {
         self.min.hash(h);
         self.max.hash(h);
     }
 }
 
-impl<T: Copy, U> Copy for TypedBox3D<T, U> {}
+impl<T: Copy, U> Copy for Box3D<T, U> {}
 
-impl<T: Copy, U> Clone for TypedBox3D<T, U> {
+impl<T: Copy, U> Clone for Box3D<T, U> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-impl<T: PartialEq, U> PartialEq<TypedBox3D<T, U>> for TypedBox3D<T, U> {
+impl<T: PartialEq, U> PartialEq<Box3D<T, U>> for Box3D<T, U> {
     fn eq(&self, other: &Self) -> bool {
         self.min.eq(&other.min) && self.max.eq(&other.max)
     }
 }
 
-impl<T: Eq, U> Eq for TypedBox3D<T, U> {}
+impl<T: Eq, U> Eq for Box3D<T, U> {}
 
-impl<T: fmt::Debug, U> fmt::Debug for TypedBox3D<T, U> {
+impl<T: fmt::Debug, U> fmt::Debug for Box3D<T, U> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypedBox3D({:?}, {:?})", self.min, self.max)
+        write!(f, "Box3D({:?}, {:?})", self.min, self.max)
     }
 }
 
-impl<T: fmt::Display, U> fmt::Display for TypedBox3D<T, U> {
+impl<T: fmt::Display, U> fmt::Display for Box3D<T, U> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "Box3D({}, {})", self.min, self.max)
     }
 }
 
-impl<T, U> TypedBox3D<T, U> {
+impl<T, U> Box3D<T, U> {
     /// Constructor.
-    pub fn new(min: TypedPoint3D<T, U>, max: TypedPoint3D<T, U>) -> Self {
-        TypedBox3D {
+    pub fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
+        Box3D {
             min,
             max,
         }
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Zero + PartialOrd,
 {
     /// Creates a Box3D of the given size, at offset zero.
     #[inline]
-    pub fn from_size(size: TypedSize3D<T, U>) -> Self {
-        let zero = TypedPoint3D::zero();
+    pub fn from_size(size: Size3D<T, U>) -> Self {
+        let zero = Point3D::zero();
         let point = size.to_vector().to_point();
-        TypedBox3D::from_points(&[zero, point])
+        Box3D::from_points(&[zero, point])
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + PartialOrd,
 {
     /// Returns true if the box has a negative volume.
     ///
     /// The common interpretation for a negative box is to consider it empty. It can be obtained
     /// by calculating the intersection of two boxes that do not intersect.
     #[inline]
@@ -111,150 +108,155 @@ where
     }
 
     /// Returns true if the size is zero or negative.
     #[inline]
     pub fn is_empty_or_negative(&self) -> bool {
         self.max.x <= self.min.x || self.max.y <= self.min.y || self.max.z <= self.min.z
     }
 
+    #[inline]
+    pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
+        if self.is_empty_or_negative() {
+            return None;
+        }
+
+        Some(NonEmpty(*self))
+    }
 
     #[inline]
     pub fn intersects(&self, other: &Self) -> bool {
         self.min.x < other.max.x
             && self.max.x > other.min.x
             && self.min.y < other.max.y
             && self.max.y > other.min.y
             && self.min.z < other.max.z
             && self.max.z > other.min.z
     }
 
     #[inline]
-    pub fn try_intersection(&self, other: &Self) -> Option<Self> {
+    pub fn try_intersection(&self, other: &Self) -> Option<NonEmpty<Self>> {
         if !self.intersects(other) {
             return None;
         }
 
-        Some(self.intersection(other))
+        Some(NonEmpty(self.intersection(other)))
     }
 
     pub fn intersection(&self, other: &Self) -> Self {
-        let intersection_min = TypedPoint3D::new(
+        let intersection_min = Point3D::new(
             max(self.min.x, other.min.x),
             max(self.min.y, other.min.y),
             max(self.min.z, other.min.z),
         );
 
-        let intersection_max = TypedPoint3D::new(
+        let intersection_max = Point3D::new(
             min(self.max.x, other.max.x),
             min(self.max.y, other.max.y),
             min(self.max.z, other.max.z),
         );
 
-        TypedBox3D::new(
+        Box3D::new(
             intersection_min, 
             intersection_max,
         )
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Add<T, Output = T>,
 {
     /// Returns the same box3d, translated by a vector.
     #[inline]
-    #[cfg_attr(feature = "unstable", must_use)]
-    pub fn translate(&self, by: &TypedVector3D<T, U>) -> Self {
-        Self::new(self.min + *by, self.max + *by)
+    #[must_use]
+    pub fn translate(&self, by: Vector3D<T, U>) -> Self {
+        Box3D {
+            min: self.min + by,
+            max: self.max + by,
+        }
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + PartialOrd + Zero,
 {
     /// Returns true if this box3d contains the point. Points are considered
     /// in the box3d if they are on the front, left or top faces, but outside if they
     /// are on the back, right or bottom faces.
     #[inline]
-    pub fn contains(&self, other: &TypedPoint3D<T, U>) -> bool {
+    pub fn contains(&self, other: Point3D<T, U>) -> bool {
         self.min.x <= other.x && other.x < self.max.x
             && self.min.y <= other.y && other.y < self.max.y
             && self.min.z <= other.z && other.z < self.max.z
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
 {
     /// Returns true if this box3d contains the interior of the other box3d. Always
     /// returns true if other is empty, and always returns false if other is
     /// nonempty but this box3d is empty.
     #[inline]
     pub fn contains_box(&self, other: &Self) -> bool {
         other.is_empty_or_negative()
             || (self.min.x <= other.min.x && other.max.x <= self.max.x
                 && self.min.y <= other.min.y && other.max.y <= self.max.y
                 && self.min.z <= other.min.z && other.max.z <= self.max.z)
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Sub<T, Output = T>,
 {
     #[inline]
-    pub fn size(&self)-> TypedSize3D<T, U> {
-        TypedSize3D::new(
+    pub fn size(&self)-> Size3D<T, U> {
+        Size3D::new(
             self.max.x - self.min.x,
             self.max.y - self.min.y,
             self.max.z - self.min.z,
         )
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
 {
     /// Inflates the box by the specified sizes on each side respectively.
     #[inline]
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn inflate(&self, width: T, height: T, depth: T) -> Self {
-        TypedBox3D::new(
-            TypedPoint3D::new(self.min.x - width, self.min.y - height, self.min.z - depth),
-            TypedPoint3D::new(self.max.x + width, self.max.y + height, self.max.z + depth),
+        Box3D::new(
+            Point3D::new(self.min.x - width, self.min.y - height, self.min.z - depth),
+            Point3D::new(self.max.x + width, self.max.y + height, self.max.z + depth),
         )
     }
-
-    #[inline]
-    #[cfg_attr(feature = "unstable", must_use)]
-    pub fn inflate_typed(&self, width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
-        self.inflate(width.get(), height.get(), depth.get())
-    }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Zero + PartialOrd,
 {
     /// Returns the smallest box containing all of the provided points.
     pub fn from_points<I>(points: I) -> Self
     where
         I: IntoIterator,
-        I::Item: Borrow<TypedPoint3D<T, U>>,
+        I::Item: Borrow<Point3D<T, U>>,
     {
         let mut points = points.into_iter();
 
         // Need at least 2 different points for a valid box3d (ie: volume > 0).
         let (mut min_x, mut min_y, mut min_z) = match points.next() {
             Some(first) => (first.borrow().x, first.borrow().y, first.borrow().z),
-            None => return TypedBox3D::zero(),
+            None => return Box3D::zero(),
         };
         let (mut max_x, mut max_y, mut max_z) = (min_x, min_y, min_z);
 
         {
             let mut assign_min_max = |point: I::Item| {
                 let p = point.borrow();
                 if p.x < min_x {
                     min_x = p.x
@@ -273,92 +275,92 @@ where
                 }
                 if p.z > max_z {
                     max_z = p.z
                 }
             };
                     
             match points.next() {
                 Some(second) => assign_min_max(second),
-                None => return TypedBox3D::zero(),
+                None => return Box3D::zero(),
             }
 
             for point in points {
                 assign_min_max(point);
             }
         }
 
-        Self::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
+        Self::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
 {
     /// Linearly interpolate between this box3d and another box3d.
     ///
     /// `t` is expected to be between zero and one.
     #[inline]
     pub fn lerp(&self, other: Self, t: T) -> Self {
         Self::new(
             self.min.lerp(other.min, t),
             self.max.lerp(other.max, t),
         )
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + One + Add<Output = T> + Div<Output = T>,
 {
-    pub fn center(&self) -> TypedPoint3D<T, U> {
+    pub fn center(&self) -> Point3D<T, U> {
         let two = T::one() + T::one();
         (self.min + self.max.to_vector()) / two
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
 {
     #[inline]
     pub fn union(&self, other: &Self) -> Self {
-        TypedBox3D::new(
-            TypedPoint3D::new(
+        Box3D::new(
+            Point3D::new(
                 min(self.min.x, other.min.x),
                 min(self.min.y, other.min.y),
                 min(self.min.z, other.min.z),
             ),
-            TypedPoint3D::new(
+            Point3D::new(
                 max(self.max.x, other.max.x),
                 max(self.max.y, other.max.y),
                 max(self.max.z, other.max.z),
             ),
         )
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy,
 {
     #[inline]
     pub fn scale<S: Copy>(&self, x: S, y: S, z: S) -> Self
     where
         T: Mul<S, Output = T>
     {
-        TypedBox3D::new(
-            TypedPoint3D::new(self.min.x * x, self.min.y * y, self.min.z * z),
-            TypedPoint3D::new(self.max.x * x, self.max.y * y, self.max.z * z),
+        Box3D::new(
+            Point3D::new(self.min.x * x, self.min.y * y, self.min.z * z),
+            Point3D::new(self.max.x * x, self.max.y * y, self.max.z * z),
         )
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
 {
     #[inline]
     pub fn volume(&self) -> T {
         let size = self.size();
         size.width * size.height * size.depth
     }
@@ -377,241 +379,244 @@ where
 
     #[inline]
     pub fn xz_area(&self) -> T {
         let size = self.size();
         size.depth * size.width
     }
 }
 
-impl<T, U> TypedBox3D<T, U> 
+impl<T, U> Box3D<T, U> 
 where
     T: Copy + Zero,
 {
     /// Constructor, setting all sides to zero.
     pub fn zero() -> Self {
-        TypedBox3D::new(TypedPoint3D::zero(), TypedPoint3D::zero())
+        Box3D::new(Point3D::zero(), Point3D::zero())
     }
 }
 
-impl<T, U> TypedBox3D<T, U>
+impl<T, U> Box3D<T, U>
 where
     T: PartialEq,
 {
     /// Returns true if the volume is zero.
     #[inline]
     pub fn is_empty(&self) -> bool {
         self.min.x == self.max.x || self.min.y == self.max.y || self.min.z == self.max.z
     }
 }
 
-impl<T, U> Mul<T> for TypedBox3D<T, U> 
+impl<T, U> Mul<T> for Box3D<T, U>
 where
     T: Copy + Mul<T, Output = T>,
 {
     type Output = Self;
     #[inline]
     fn mul(self, scale: T) -> Self {
-        TypedBox3D::new(self.min * scale, self.max * scale)
+        Box3D::new(self.min * scale, self.max * scale)
     }
 }
 
-impl<T, U> Div<T> for TypedBox3D<T, U> 
+impl<T, U> Div<T> for Box3D<T, U>
 where
     T: Copy + Div<T, Output = T>,
 {
     type Output = Self;
     #[inline]
     fn div(self, scale: T) -> Self {
-        TypedBox3D::new(self.min / scale, self.max / scale)
+        Box3D::new(self.min / scale, self.max / scale)
     }
 }
 
-impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox3D<T, U1> 
+impl<T, U1, U2> Mul<Scale<T, U1, U2>> for Box3D<T, U1>
 where
     T: Copy + Mul<T, Output = T>,
 {
-    type Output = TypedBox3D<T, U2>;
+    type Output = Box3D<T, U2>;
     #[inline]
-    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U2> {
-        TypedBox3D::new(self.min * scale, self.max * scale)
+    fn mul(self, scale: Scale<T, U1, U2>) -> Box3D<T, U2> {
+        Box3D::new(self.min * scale, self.max * scale)
     }
 }
 
-impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox3D<T, U2> 
+impl<T, U1, U2> Div<Scale<T, U1, U2>> for Box3D<T, U2>
 where
     T: Copy + Div<T, Output = T>,
 {
-    type Output = TypedBox3D<T, U1>;
+    type Output = Box3D<T, U1>;
     #[inline]
-    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U1> {
-        TypedBox3D::new(self.min / scale, self.max / scale)
+    fn div(self, scale: Scale<T, U1, U2>) -> Box3D<T, U1> {
+        Box3D::new(self.min / scale, self.max / scale)
     }
 }
 
-impl<T, Unit> TypedBox3D<T, Unit> 
+impl<T, Unit> Box3D<T, Unit>
 where
     T: Copy,
 {
     /// Drop the units, preserving only the numeric value.
-    pub fn to_untyped(&self) -> Box3D<T> {
-        TypedBox3D::new(self.min.to_untyped(), self.max.to_untyped())
+    #[inline]
+    pub fn to_untyped(&self) -> Box3D<T, UnknownUnit> {
+        Box3D {
+            min: self.min.to_untyped(),
+            max: self.max.to_untyped(),
+        }
     }
 
     /// Tag a unitless value with units.
-    pub fn from_untyped(c: &Box3D<T>) -> TypedBox3D<T, Unit> {
-        TypedBox3D::new(
-            TypedPoint3D::from_untyped(&c.min),
-            TypedPoint3D::from_untyped(&c.max),
-        )
+    #[inline]
+    pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, Unit> {
+        Box3D {
+            min: Point3D::from_untyped(c.min),
+            max: Point3D::from_untyped(c.max),
+        }
     }
 }
 
-impl<T0, Unit> TypedBox3D<T0, Unit> 
+impl<T0, Unit> Box3D<T0, Unit>
 where
     T0: NumCast + Copy,
 {
     /// 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) -> TypedBox3D<T1, Unit> {
-        TypedBox3D::new(
+    pub fn cast<T1: NumCast + Copy>(&self) -> Box3D<T1, Unit> {
+        Box3D::new(
             self.min.cast(),
             self.max.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<TypedBox3D<T1, Unit>> {
+    pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box3D<T1, Unit>> {
         match (self.min.try_cast(), self.max.try_cast()) {
-            (Some(a), Some(b)) => Some(TypedBox3D::new(a, b)),
+            (Some(a), Some(b)) => Some(Box3D::new(a, b)),
             _ => None,
         }
     }
 }
 
-impl<T, U> TypedBox3D<T, U> 
+impl<T, U> Box3D<T, U>
 where
     T: Round,
 {
     /// Return a box3d with edges rounded to integer coordinates, such that
     /// the returned box3d has the same set of pixel centers as the original
     /// one.
     /// Values equal to 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)]
+    #[must_use]
     pub fn round(&self) -> Self {
-        TypedBox3D::new(self.min.round(), self.max.round())
+        Box3D::new(self.min.round(), self.max.round())
     }
 }
 
-impl<T, U> TypedBox3D<T, U> 
+impl<T, U> Box3D<T, U>
 where
     T: Floor + Ceil,
 {
     /// Return a box3d with faces/edges rounded to integer coordinates, such that
     /// the original box3d contains the resulting box3d.
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn round_in(&self) -> Self {
-        TypedBox3D {
+        Box3D {
             min: self.min.ceil(),
             max: self.max.floor(),
         }
     }
 
     /// Return a box3d with faces/edges rounded to integer coordinates, such that
     /// the original box3d is contained in the resulting box3d.
-    #[cfg_attr(feature = "unstable", must_use)]
+    #[must_use]
     pub fn round_out(&self) -> Self {
-        TypedBox3D {
+        Box3D {
             min: self.min.floor(),
             max: self.max.ceil(),
         }
     }
 }
 
 // Convenience functions for common casts
-impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
+impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
     /// Cast into an `f32` box3d.
-    pub fn to_f32(&self) -> TypedBox3D<f32, Unit> {
+    pub fn to_f32(&self) -> Box3D<f32, Unit> {
         self.cast()
     }
 
     /// Cast into an `f64` box3d.
-    pub fn to_f64(&self) -> TypedBox3D<f64, Unit> {
+    pub fn to_f64(&self) -> Box3D<f64, Unit> {
         self.cast()
     }
 
     /// Cast into an `usize` box3d, truncating decimals if any.
     ///
     /// When casting from floating point cuboids, 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) -> TypedBox3D<usize, Unit> {
+    pub fn to_usize(&self) -> Box3D<usize, Unit> {
         self.cast()
     }
 
     /// Cast into an `u32` box3d, truncating decimals if any.
     ///
     /// When casting from floating point cuboids, 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) -> TypedBox3D<u32, Unit> {
+    pub fn to_u32(&self) -> Box3D<u32, Unit> {
         self.cast()
     }
 
     /// Cast into an `i32` box3d, truncating decimals if any.
     ///
     /// When casting from floating point cuboids, 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) -> TypedBox3D<i32, Unit> {
+    pub fn to_i32(&self) -> Box3D<i32, Unit> {
         self.cast()
     }
 
     /// Cast into an `i64` box3d, truncating decimals if any.
     ///
     /// When casting from floating point cuboids, 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) -> TypedBox3D<i64, Unit> {
+    pub fn to_i64(&self) -> Box3D<i64, Unit> {
         self.cast()
     }
 }
 
-impl<T, U> From<TypedSize3D<T, U>> for TypedBox3D<T, U>
+impl<T, U> From<Size3D<T, U>> for Box3D<T, U>
 where 
     T: Copy + Zero + PartialOrd,
 {
-    fn from(b: TypedSize3D<T, U>) -> Self {
+    fn from(b: Size3D<T, U>) -> Self {
         Self::from_size(b)
     }
 }
 
-/// Shorthand for `TypedBox3D::new(TypedPoint3D::new(x1, y1, z1), TypedPoint3D::new(x2, y2, z2))`.
-pub fn box3d<T: Copy, U>(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) -> TypedBox3D<T, U> {
-    TypedBox3D::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
+/// Shorthand for `Box3D::new(Point3D::new(x1, y1, z1), Point3D::new(x2, y2, z2))`.
+pub fn box3d<T: Copy, U>(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) -> Box3D<T, U> {
+    Box3D::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
 }
 
 #[cfg(test)]
 mod tests {
-    use vector::vec3;
-    use size::size3;
-    use point::{point3, Point3D};
-    use super::*;
+    use {point3, size3, vec3};
+    use default::{Box3D, Point3D};
 
     #[test]
     fn test_new() {
         let b = Box3D::new(point3(-1.0, -1.0, -1.0), point3(1.0, 1.0, 1.0));
         assert!(b.min.x == -1.0);
         assert!(b.min.y == -1.0);
         assert!(b.min.z == -1.0);
         assert!(b.max.x == 1.0);
@@ -709,17 +714,17 @@ mod tests {
 
     #[test]
     fn test_translate() {
         let size = size3(15.0, 15.0, 200.0);
         let mut center = (size / 2.0).to_vector().to_point();
         let b = Box3D::from_size(size);
         assert!(b.center() == center);
         let translation = vec3(10.0, 2.5, 9.5);
-        let b = b.translate(&translation);
+        let b = b.translate(translation);
         center += translation;
         assert!(b.center() == center);
         assert!(b.max.x == 25.0);
         assert!(b.max.y == 17.5);
         assert!(b.max.z == 209.5);
         assert!(b.min.x == 10.0);
         assert!(b.min.y == 2.5);
         assert!(b.min.z == 9.5);
@@ -803,17 +808,17 @@ mod tests {
         assert!(b.size().width == 10.0);
         assert!(b.size().height == 10.0);
         assert!(b.size().depth == 10.0);
     }
 
     #[test]
     fn test_contains() {
         let b = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
-        assert!(b.contains(&point3(-15.3, 10.5, 18.4)));
+        assert!(b.contains(point3(-15.3, 10.5, 18.4)));
     }
 
     #[test]
     fn test_contains_box() {
         let b1 = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
         let b2 = Box3D::from_points(&[point3(-14.3, -16.5, -19.3), point3(6.7, 17.6, 2.5)]);
         assert!(b1.contains_box(&b2));
     }
--- a/third_party/rust/euclid/src/homogen.rs
+++ b/third_party/rust/euclid/src/homogen.rs
@@ -2,98 +2,158 @@
 // 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 point::{Point2D, Point3D};
+use vector::{Vector2D, Vector3D};
 
 use num::{One, Zero};
 
 use core::fmt;
 use core::marker::PhantomData;
 use core::ops::Div;
+use core::cmp::{Eq, PartialEq};
+use core::hash::{Hash};
+#[cfg(feature = "serde")]
+use serde;
 
 
 /// Homogeneous vector in 3D space.
-#[derive(EuclidMatrix)]
 #[repr(C)]
 pub struct HomogeneousVector<T, U> {
     pub x: T,
     pub y: T,
     pub z: T,
     pub w: T,
     #[doc(hidden)]
     pub _unit: PhantomData<U>,
 }
 
+impl<T: Copy, U> Copy for HomogeneousVector<T, U> {}
+
+impl<T: Clone, U> Clone for HomogeneousVector<T, U> {
+    fn clone(&self) -> Self {
+        HomogeneousVector {
+            x: self.x.clone(),
+            y: self.y.clone(),
+            z: self.z.clone(),
+            w: self.w.clone(),
+            _unit: PhantomData,
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, T, U> serde::Deserialize<'de> for HomogeneousVector<T, U>
+    where T: serde::Deserialize<'de>
+{
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where D: serde::Deserializer<'de>
+    {
+        let (x, y, z, w) = try!(serde::Deserialize::deserialize(deserializer));
+        Ok(HomogeneousVector { x, y, z, w, _unit: PhantomData })
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<T, U> serde::Serialize for HomogeneousVector<T, U>
+    where T: serde::Serialize
+{
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where S: serde::Serializer
+    {
+        (&self.x, &self.y, &self.z, &self.w).serialize(serializer)
+    }
+}
+
+impl<T, U> Eq for HomogeneousVector<T, U> where T: Eq {}
+
+impl<T, U> PartialEq for HomogeneousVector<T, U>
+    where T: PartialEq
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.x == other.x && self.y == other.y && self.z == other.z && self.w == other.w
+    }
+}
+
+impl<T, U> Hash for HomogeneousVector<T, U>
+    where T: Hash
+{
+    fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
+        self.x.hash(h);
+        self.y.hash(h);
+        self.z.hash(h);
+        self.w.hash(h);
+    }
+}
 
 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>> {
+    pub fn to_point2d(&self) -> Option<Point2D<T, U>> {
         if self.w > T::zero() {
-            Some(TypedPoint2D::new(self.x / self.w, self.y / self.w))
+            Some(Point2D::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>> {
+    pub fn to_point3d(&self) -> Option<Point3D<T, U>> {
         if self.w > T::zero() {
-            Some(TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w))
+            Some(Point3D::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> {
+impl<T: Zero, U> From<Vector2D<T, U>> for HomogeneousVector<T, U> {
     #[inline]
-    fn from(v: TypedVector2D<T, U>) -> Self {
+    fn from(v: Vector2D<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> {
+impl<T: Zero, U> From<Vector3D<T, U>> for HomogeneousVector<T, U> {
     #[inline]
-    fn from(v: TypedVector3D<T, U>) -> Self {
+    fn from(v: Vector3D<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> {
+impl<T: Zero + One, U> From<Point2D<T, U>> for HomogeneousVector<T, U> {
     #[inline]
-    fn from(p: TypedPoint2D<T, U>) -> Self {
+    fn from(p: Point2D<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> {
+impl<T: One, U> From<Point3D<T, U>> for HomogeneousVector<T, U> {
     #[inline]
-    fn from(p: TypedPoint3D<T, U>) -> Self {
+    fn from(p: Point3D<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)
     }
@@ -104,17 +164,17 @@ impl<T: fmt::Display, U> fmt::Display fo
         write!(formatter, "({},{},{},{})", self.x, self.y, self.z, self.w)
     }
 }
 
 
 #[cfg(test)]
 mod homogeneous {
     use super::HomogeneousVector;
-    use point::{Point2D, Point3D};
+    use default::{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]
--- a/third_party/rust/euclid/src/length.rs
+++ b/third_party/rust/euclid/src/length.rs
@@ -3,17 +3,17 @@
 //
 // 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 scale::Scale;
 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};
@@ -25,20 +25,20 @@ use core::fmt;
 ///
 /// `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.
+/// You can multiply a `Length` by a `scale::Scale` to convert it from one unit to
+/// another. See the [`Scale`] docs for an example.
 ///
-/// [`TypedScale`]: struct.TypedScale.html
+/// [`Scale`]: struct.Scale.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)
     }
 }
@@ -136,20 +136,20 @@ impl<U, T: Clone + Saturating> Saturatin
 
     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>;
+    type Output = Scale<T, Src, Dst>;
     #[inline]
-    fn div(self, other: Length<T, Src>) -> TypedScale<T, Src, Dst> {
-        TypedScale::new(self.get() / other.get())
+    fn div(self, other: Length<T, Src>) -> Scale<T, Src, Dst> {
+        Scale::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 {
@@ -178,29 +178,29 @@ impl<T: Copy + Div<T, Output = T>, U> Di
 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> {
+impl<Src, Dst, T: Clone + Mul<T, Output = T>> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
     type Output = Length<T, Dst>;
     #[inline]
-    fn mul(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Dst> {
+    fn mul(self, scale: Scale<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> {
+impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
     type Output = Length<T, Src>;
     #[inline]
-    fn div(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Src> {
+    fn div(self, scale: Scale<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]
@@ -262,17 +262,17 @@ where
 }
 
 #[cfg(test)]
 mod tests {
     use super::Length;
     use num::Zero;
 
     use num_traits::Saturating;
-    use scale::TypedScale;
+    use scale::Scale;
     use core::f32::INFINITY;
 
     enum Inch {}
     enum Mm {}
     enum Cm {}
     enum Second {}
 
     #[cfg(feature = "serde")]
@@ -374,31 +374,31 @@ mod tests {
 
         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
+        // Division results in a Scale 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);
+        let expected: Scale<f32, Second, Cm> = Scale::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 cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
 
         let result = length_mm * cm_per_mm;
 
         let expected: Length<f32, Cm> = Length::new(1.0);
         assert_eq!(result, expected);
     }
 
     #[test]
@@ -419,17 +419,17 @@ mod tests {
 
         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 cm_per_second: Scale<f32, Second, Cm> = Scale::new(10.0);
 
         let result = length / cm_per_second;
 
         let expected: Length<f32, Second> = Length::new(0.5);
         assert_eq!(result, expected);
     }
 
     #[test]
@@ -509,12 +509,12 @@ mod tests {
     #[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);
+        let expected: Scale<f32, Cm, Cm> = Scale::new(INFINITY);
         assert_eq!(result, expected);
     }
 }
--- a/third_party/rust/euclid/src/lib.rs
+++ b/third_party/rust/euclid/src/lib.rs
@@ -2,96 +2,76 @@
 // 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
+//! This unit system is not mandatory and all * structures have an alias
 //! with the default unit: `UnknownUnit`.
-//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
+//! for example ```Point2D<T>``` is equivalent to ```Point2D<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 type ScreenPoint = Point2D<f32, ScreenSpace>;
+//! pub type ScreenSize = Size2D<f32, ScreenSpace>;
 //! pub struct WorldSpace;
-//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
-//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
+//! pub type WorldPoint = Point3D<f32, WorldSpace>;
+//! pub type ProjectionMatrix = Transform3D<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;
-#[macro_use]
-extern crate euclid_macros;
 extern crate num_traits;
 #[cfg(test)]
-extern crate rand;
-#[cfg(test)]
 use std as core;
 
-pub use box2d::{TypedBox2D, Box2D};
+pub use box2d::Box2D;
 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 scale::Scale;
+pub use transform2d::Transform2D;
+pub use transform3d::Transform3D;
+pub use point::{Point2D, Point3D, point2, point3};
+pub use vector::{Vector2D, Vector3D, vec2, vec3};
 pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
 pub use homogen::HomogeneousVector;
+pub use nonempty::NonEmpty;
 
-pub use rect::{rect, Rect, TypedRect};
-pub use rigid::{RigidTransform3D, TypedRigidTransform3D};
-pub use box3d::{box3d, Box3D, TypedBox3D};
-pub use translation::{TypedTranslation2D, TypedTranslation3D};
-pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
-pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
-pub use size::{Size2D, TypedSize2D, size2};
+pub use rect::{rect, Rect};
+pub use rigid::{RigidTransform3D};
+pub use box3d::{box3d, Box3D};
+pub use translation::{Translation2D, Translation3D};
+pub use rotation::{Angle, Rotation2D, Rotation3D};
+pub use side_offsets::SideOffsets2D;
+pub use size::{Size2D, Size3D, size2, size3};
 pub use trig::Trig;
 
 #[macro_use]
 mod macros;
 
 pub mod approxeq;
 pub mod approxord;
 mod box2d;
@@ -106,36 +86,35 @@ mod scale;
 mod side_offsets;
 mod size;
 mod transform2d;
 mod transform3d;
 mod translation;
 mod trig;
 mod vector;
 mod box3d;
+mod nonempty;
 
 /// The default unit.
 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 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;
+pub mod default {
+    use super::UnknownUnit;
+    pub type Point2D<T> = super::Point2D<T, UnknownUnit>;
+    pub type Point3D<T> = super::Point3D<T, UnknownUnit>;
+    pub type Vector2D<T> = super::Vector2D<T, UnknownUnit>;
+    pub type Vector3D<T> = super::Vector3D<T, UnknownUnit>;
+    pub type HomogeneousVector<T> = super::HomogeneousVector<T, UnknownUnit>;
+    pub type Size2D<T> = super::Size2D<T, UnknownUnit>;
+    pub type Size3D<T> = super::Size3D<T, UnknownUnit>;
+    pub type Rect<T> = super::Rect<T, UnknownUnit>;
+    pub type Box2D<T> = super::Box2D<T, UnknownUnit>;
+    pub type Box3D<T> = super::Box3D<T, UnknownUnit>;
+    pub type SideOffsets2D<T> = super::SideOffsets2D<T, UnknownUnit>;
+    pub type Transform2D<T> = super::Transform2D<T, UnknownUnit, UnknownUnit>;
+    pub type Transform3D<T> = super::Transform3D<T, UnknownUnit, UnknownUnit>;
+    pub type Rotation2D<T> = super::Rotation2D<T, UnknownUnit, UnknownUnit>;
+    pub type Rotation3D<T> = super::Rotation3D<T, UnknownUnit, UnknownUnit>;
+    pub type Translation3D<T> = super::Translation3D<T, UnknownUnit, UnknownUnit>;
+    pub type Scale<T> = super::Scale<T, UnknownUnit, UnknownUnit>;
+    pub type RigidTransform3D<T> = super::RigidTransform3D<T, UnknownUnit, UnknownUnit>;
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/euclid/src/nonempty.rs
@@ -0,0 +1,259 @@
+use {Rect, Box2D, Box3D, Vector2D, Vector3D, size2, point2, point3};
+use approxord::{min, max};
+use num::Zero;
+use core::ops::Deref;
+use core::ops::{Add, Sub};
+use core::cmp::{PartialEq};
+
+
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", serde(transparent))]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct NonEmpty<T>(pub(crate) T);
+
+impl<T> Deref for NonEmpty<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> NonEmpty<T> {
+    #[inline]
+    pub fn get(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T, U> NonEmpty<Rect<T, U>>
+where
+    T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
+{
+    #[inline]
+    pub fn union(&self, other: &NonEmpty<Rect<T, U>>) -> NonEmpty<Rect<T, U>> {
+        let origin = point2(
+            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());
+
+        NonEmpty(Rect {
+            origin,
+            size: size2(
+                lower_right_x - origin.x,
+                lower_right_y - origin.y,
+            ),
+        })
+    }
+
+    #[inline]
+    pub fn contains_rect(&self, rect: &Self) -> bool {
+        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]
+    pub fn translate(&self, by: Vector2D<T, U>) -> Self {
+        NonEmpty(self.0.translate(by))
+    }
+}
+
+impl<T, U> NonEmpty<Box2D<T, U>>
+where
+    T: Copy + PartialOrd,
+{
+    #[inline]
+    pub fn union(&self, other: &NonEmpty<Box2D<T, U>>) -> NonEmpty<Box2D<T, U>> {
+        NonEmpty(Box2D {
+            min: point2(
+                min(self.min.x, other.min.x),
+                min(self.min.y, other.min.y),
+            ),
+            max: point2(
+                max(self.max.x, other.max.x),
+                max(self.max.y, other.max.y),
+            ),
+        })
+    }
+
+    /// Returns true if this box contains the interior of the other box.
+    #[inline]
+    pub fn contains_box(&self, other: &Self) -> bool {
+        self.min.x <= other.min.x
+            && other.max.x <= self.max.x
+            && self.min.y <= other.min.y
+            && other.max.y <= self.max.y
+    }
+}
+
+impl<T, U> NonEmpty<Box2D<T, U>>
+where
+    T: Copy + Add<T, Output = T>,
+{
+    #[inline]
+    pub fn translate(&self, by: Vector2D<T, U>) -> Self {
+        NonEmpty(self.0.translate(by))
+    }
+}
+
+impl<T, U> NonEmpty<Box3D<T, U>>
+where
+    T: Copy + PartialOrd,
+{
+    #[inline]
+    pub fn union(&self, other: &NonEmpty<Box3D<T, U>>) -> NonEmpty<Box3D<T, U>> {
+        NonEmpty(Box3D {
+            min: point3(
+                min(self.min.x, other.min.x),
+                min(self.min.y, other.min.y),
+                min(self.min.z, other.min.z),
+            ),
+            max: point3(
+                max(self.max.x, other.max.x),
+                max(self.max.y, other.max.y),
+                max(self.max.z, other.max.z),
+            ),
+        })
+    }
+
+    /// Returns true if this box contains the interior of the other box.
+    #[inline]
+    pub fn contains_box(&self, other: &Self) -> bool {
+        self.min.x <= other.min.x
+            && other.max.x <= self.max.x
+            && self.min.y <= other.min.y
+            && other.max.y <= self.max.y
+            && self.min.z <= other.min.z
+            && other.max.z <= self.max.z
+    }
+}
+
+impl<T, U> NonEmpty<Box3D<T, U>>
+where
+    T: Copy + Add<T, Output = T>,
+{
+    #[inline]
+    pub fn translate(&self, by: Vector3D<T, U>) -> Self {
+        NonEmpty(self.0.translate(by))
+    }
+}
+
+#[test]
+fn empty_nonempty() {
+    use default;
+
+    // zero-width
+    let box1: default::Box2D<i32> = Box2D {
+        min: point2(-10, 2),
+        max: point2(-10, 12),
+    };
+    // zero-height
+    let box2: default::Box2D<i32> = Box2D {
+        min: point2(0, 11),
+        max: point2(2, 11),
+    };
+    // negative width
+    let box3: default::Box2D<i32> = Box2D {
+        min: point2(1, 11),
+        max: point2(0, 12),
+    };
+    // negative height
+    let box4: default::Box2D<i32> = Box2D {
+        min: point2(0, 11),
+        max: point2(5, 10),
+    };
+
+    assert!(box1.to_non_empty().is_none());
+    assert!(box2.to_non_empty().is_none());
+    assert!(box3.to_non_empty().is_none());
+    assert!(box4.to_non_empty().is_none());
+}
+
+#[test]
+fn nonempty_union() {
+    use default;
+
+    let box1: default::Box2D<i32> = Box2D {
+        min: point2(-10, 2),
+        max: point2(15, 12),
+    };
+    let box2 = Box2D {
+        min: point2(-2, -5),
+        max: point2(10, 5),
+    };
+
+    assert_eq!(box1.union(&box2), *box1.to_non_empty().unwrap().union(&box2.to_non_empty().unwrap()));
+
+    let box3: default::Box3D<i32> = Box3D {
+        min: point3(1, -10, 2),
+        max: point3(6, 15, 12),
+    };
+    let box4 = Box3D {
+        min: point3(0, -2, -5),
+        max: point3(7, 10, 5),
+    };
+
+    assert_eq!(box3.union(&box4), *box3.to_non_empty().unwrap().union(&box4.to_non_empty().unwrap()));
+
+    let rect1: default::Rect<i32> = Rect {
+        origin: point2(1, 2),
+        size: size2(3, 4),
+    };
+    let rect2 = Rect {
+        origin: point2(-1, 5),
+        size: size2(1, 10),
+    };
+
+    assert_eq!(rect1.union(&rect2), *rect1.to_non_empty().unwrap().union(&rect2.to_non_empty().unwrap()));
+}
+
+#[test]
+fn nonempty_contains() {
+    use default;
+    use {vec2, vec3};
+
+    let r: NonEmpty<default::Rect<i32>> = Rect {
+        origin: point2(-20, 15),
+        size: size2(100, 200),
+    }.to_non_empty().unwrap();
+
+    assert!(r.contains_rect(&r));
+    assert!(!r.contains_rect(&r.translate(vec2(1, 0))));
+    assert!(!r.contains_rect(&r.translate(vec2(-1, 0))));
+    assert!(!r.contains_rect(&r.translate(vec2(0, 1))));
+    assert!(!r.contains_rect(&r.translate(vec2(0, -1))));
+
+    let b: NonEmpty<default::Box2D<i32>> = Box2D {
+        min: point2(-10, 5),
+        max: point2(30, 100),
+    }.to_non_empty().unwrap();
+
+    assert!(b.contains_box(&b));
+    assert!(!b.contains_box(&b.translate(vec2(1, 0))));
+    assert!(!b.contains_box(&b.translate(vec2(-1, 0))));
+    assert!(!b.contains_box(&b.translate(vec2(0, 1))));
+    assert!(!b.contains_box(&b.translate(vec2(0, -1))));
+
+    let b: NonEmpty<default::Box3D<i32>> = Box3D {
+        min: point3(-1, -10, 5),
+        max: point3(10, 30, 100),
+    }.to_non_empty().unwrap();
+
+    assert!(b.contains_box(&b));
+    assert!(!b.contains_box(&b.translate(vec3(0, 1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(0, -1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(0, 0, 1))));
+    assert!(!b.contains_box(&b.translate(vec3(0, 0, -1))));
+    assert!(!b.contains_box(&b.translate(vec3(1, 1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(1, -1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(1, 0, 1))));
+    assert!(!b.contains_box(&b.translate(vec3(1, 0, -1))));
+    assert!(!b.contains_box(&b.translate(vec3(-1, 1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(-1, -1, 0))));
+    assert!(!b.contains_box(&b.translate(vec3(-1, 0, 1))));
+    assert!(!b.contains_box(&b.translate(vec3(-1, 0, -1))));
+}
--- a/third_party/rust/euclid/src/point.rs
+++ b/third_party/rust/euclid/src/point.rs
@@ -5,484 +5,578 @@
 // 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, TypedSize3D};
+use scale::Scale;
+use size::{Size2D, Size3D};
 #[cfg(feature = "mint")]
 use mint;
 use num::*;
 use num_traits::{Float, NumCast};
-use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
+use vector::{Vector2D, Vector3D, vec2, vec3};
 use core::fmt;
 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
 use core::marker::PhantomData;
+use core::cmp::{Eq, PartialEq};
+use core::hash::{Hash};
+#[cfg(feature = "serde")]
+use serde;
 
 /// A 2d Point tagged with a unit.
-#[derive(EuclidMatrix)]
 #[repr(C)]
-pub struct TypedPoint2D<T, U> {
+pub struct Point2D<T, U> {
     pub x: T,
     pub y: T,
     #[doc(hidden)]
     pub _unit: PhantomData<U>,
 }
 
-mint_vec!(TypedPoint2D[x, y] = Point2);
+impl<T: Copy, U> Copy for Point2D<T, U> {}
+
+impl<T: Clone, U> Clone for Point2D<T, U> {
+    fn clone(&self) -> Self {
+        Point2D {
+            x: self.x.clone(),
+            y: self.y.clone(),
+            _unit: PhantomData,
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, T, U> serde::Deserialize<'de> for Point2D<T, U>
+    where T: serde::Deserialize<'de>
+{
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where D: serde::Deserializer<'de>
+    {
+        let (x, y) = try!(serde::Deserialize::deserialize(deserializer));
+        Ok(Point2D { x, y, _unit: PhantomData })
+    }
+}
 
-/// Default 2d point type with no unit.
-///
-/// `Point2D` provides the same methods as `TypedPoint2D`.
-pub type Point2D<T> = TypedPoint2D<T, UnknownUnit>;
+#[cfg(feature = "serde")]
+impl<T, U> serde::Serialize for Point2D<T, U>
+    where T: serde::Serialize
+{
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where S: serde::Serializer
+    {
+        (&self.x, &self.y).serialize(serializer)
+    }
+}
+
+impl<T, U> Eq for Point2D<T, U> where T: Eq {}
 
-impl<T: Copy + Zero, U> TypedPoint2D<T, U> {
+impl<T, U> PartialEq for Point2D<T, U>
+    where T: PartialEq
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.x == other.x && self.y == other.y
+    }
+}
+
+impl<T, U> Hash for Point2D<T, U>
+    where T: Hash
+{
+    fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
+        self.x.hash(h);
+        self.y.hash(h);
+    }
+}
+
+mint_vec!(Point2D[x, y] = Point2);
+
+impl<T: Copy + Zero, U> Point2D<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> {
+    pub fn to_3d(&self) -> Point3D<T, U> {
         point3(self.x, self.y, Zero::zero())
     }
 }
 
-impl<T: fmt::Debug, U> fmt::Debug for TypedPoint2D<T, U> {
+impl<T: fmt::Debug, U> fmt::Debug for Point2D<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> {
+impl<T: fmt::Display, U> fmt::Display for Point2D<T, U> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "({},{})", self.x, self.y)
     }
 }
 
-impl<T: Default, U> Default for TypedPoint2D<T, U> {
+impl<T: Default, U> Default for Point2D<T, U> {
     fn default() -> Self {
-        TypedPoint2D::new(Default::default(), Default::default())
+        Point2D::new(Default::default(), Default::default())
     }
 }
 
-impl<T, U> TypedPoint2D<T, U> {
+impl<T, U> Point2D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T) -> Self {
-        TypedPoint2D {
+        Point2D {
             x,
             y,
             _unit: PhantomData,
         }
     }
 }
 
-impl<T: Copy, U> TypedPoint2D<T, U> {
-    /// Constructor taking properly typed Lengths instead of scalar values.
+impl<T: Copy, U> Point2D<T, U> {
+    /// Constructor taking properly  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> {
+    pub fn extend(&self, z: T) -> Point3D<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)
+    pub fn to_vector(&self) -> Vector2D<T, U> {
+        Vector2D {
+            x: self.x,
+            y: self.y,
+            _unit: PhantomData,
+        }
     }
 
     /// 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> {
+    pub fn to_untyped(&self) -> Point2D<T, UnknownUnit> {
         point2(self.x, self.y)
     }
 
     /// Tag a unitless value with units.
     #[inline]
-    pub fn from_untyped(p: &Point2D<T>) -> Self {
+    pub fn from_untyped(p: Point2D<T, UnknownUnit>) -> Self {
         point2(p.x, p.y)
     }
 
     #[inline]
     pub fn to_array(&self) -> [T; 2] {
         [self.x, self.y]
     }
 
     #[inline]
     pub fn to_tuple(&self) -> (T, T) {
         (self.x, self.y)
     }
 }
 
-impl<T: Copy + Add<T, Output = T>, U> TypedPoint2D<T, U> {
+impl<T: Copy + Add<T, Output = T>, U> Point2D<T, U> {
     #[inline]
-    pub fn add_size(&self, other: &TypedSize2D<T, U>) -> Self {
+    pub fn add_size(&self, other: &Size2D<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> {
+impl<T: Copy + Add<T, Output = T>, U> Add<Size2D<T, U>> for Point2D<T, U> {
     type Output = Self;
     #[inline]
-    fn add(self, other: TypedSize2D<T, U>) -> Self {
+    fn add(self, other: Size2D<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> {
+impl<T: Copy + Add<T, Output = T>, U> AddAssign<Vector2D<T, U>> for Point2D<T, U> {
     #[inline]
-    fn add_assign(&mut self, other: TypedVector2D<T, U>) {
+    fn add_assign(&mut self, other: Vector2D<T, U>) {
         *self = *self + other
     }
 }
 
-impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<Vector2D<T, U>> for Point2D<T, U> {
     #[inline]
-    fn sub_assign(&mut self, other: TypedVector2D<T, U>) {
+    fn sub_assign(&mut self, other: Vector2D<T, U>) {
         *self = *self - other
     }
 }
 
-impl<T: Copy + Add<T, Output = T>, U> Add<TypedVector2D<T, U>> for TypedPoint2D<T, U> {
+impl<T: Copy + Add<T, Output = T>, U> Add<Vector2D<T, U>> for Point2D<T, U> {
     type Output = Self;
     #[inline]
-    fn add(self, other: TypedVector2D<T, U>) -> Self {
+    fn add(self, other: Vector2D<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>;
+impl<T: Copy + Sub<T, Output = T>, U> Sub for Point2D<T, U> {
+    type Output = Vector2D<T, U>;
     #[inline]
-    fn sub(self, other: Self) -> TypedVector2D<T, U> {
+    fn sub(self, other: Self) -> Vector2D<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> {
+impl<T: Copy + Sub<T, Output = T>, U> Sub<Vector2D<T, U>> for Point2D<T, U> {
     type Output = Self;
     #[inline]
-    fn sub(self, other: TypedVector2D<T, U>) -> Self {
+    fn sub(self, other: Vector2D<T, U>) -> Self {
         point2(self.x - other.x, self.y - other.y)
     }
 }
 
-impl<T: Float, U> TypedPoint2D<T, U> {
+impl<T: Float, U> Point2D<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> {
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Point2D<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> {
+impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Point2D<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> {
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for Point2D<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> {
+impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Point2D<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>;
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<Scale<T, U1, U2>> for Point2D<T, U1> {
+    type Output = Point2D<T, U2>;
     #[inline]
-    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedPoint2D<T, U2> {
+    fn mul(self, scale: Scale<T, U1, U2>) -> Point2D<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>;
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Point2D<T, U2> {
+    type Output = Point2D<T, U1>;
     #[inline]
-    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedPoint2D<T, U1> {
+    fn div(self, scale: Scale<T, U1, U2>) -> Point2D<T, U1> {
         point2(self.x / scale.get(), self.y / scale.get())
     }
 }
 
-impl<T: Round, U> TypedPoint2D<T, U> {
+impl<T: Round, U> Point2D<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)]
+    #[must_use]
     pub fn round(&self) -> Self {
         point2(self.x.round(), self.y.round())
     }
 }
 
-impl<T: Ceil, U> TypedPoint2D<T, U> {
+impl<T: Ceil, U> Point2D<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)]
+    #[must_use]
     pub fn ceil(&self) -> Self {
         point2(self.x.ceil(), self.y.ceil())
     }
 }
 
-impl<T: Floor, U> TypedPoint2D<T, U> {
+impl<T: Floor, U> Point2D<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)]
+    #[must_use]
     pub fn floor(&self) -> Self {
         point2(self.x.floor(), self.y.floor())
     }
 }
 
-impl<T: NumCast + Copy, U> TypedPoint2D<T, U> {
+impl<T: NumCast + Copy, U> Point2D<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> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> Point2D<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>> {
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Point2D<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> {
+    pub fn to_f32(&self) -> Point2D<f32, U> {
         self.cast()
     }
 
     /// Cast into an `f64` point.
     #[inline]
-    pub fn to_f64(&self) -> TypedPoint2D<f64, U> {
+    pub fn to_f64(&self) -> Point2D<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> {
+    pub fn to_usize(&self) -> Point2D<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> {
+    pub fn to_u32(&self) -> Point2D<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> {
+    pub fn to_i32(&self) -> Point2D<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> {
+    pub fn to_i64(&self) -> Point2D<i64, U> {
         self.cast()
     }
 }
 
-impl<T, U> TypedPoint2D<T, U>
+impl<T, U> Point2D<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> {
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<Point2D<T, U>> for Point2D<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> {
+impl<T: Copy, U> Into<[T; 2]> for Point2D<T, U> {
     fn into(self) -> [T; 2] {
         self.to_array()
     }
 }
 
-impl<T: Copy, U> From<[T; 2]> for TypedPoint2D<T, U> {
+impl<T: Copy, U> From<[T; 2]> for Point2D<T, U> {
     fn from(array: [T; 2]) -> Self {
         point2(array[0], array[1])
     }
 }
 
-impl<T: Copy, U> Into<(T, T)> for TypedPoint2D<T, U> {
+impl<T: Copy, U> Into<(T, T)> for Point2D<T, U> {
     fn into(self) -> (T, T) {
         self.to_tuple()
     }
 }
 
-impl<T: Copy, U> From<(T, T)> for TypedPoint2D<T, U> {
+impl<T: Copy, U> From<(T, T)> for Point2D<T, U> {
     fn from(tuple: (T, T)) -> Self {
         point2(tuple.0, tuple.1)
     }
 }
 
 /// A 3d Point tagged with a unit.
-#[derive(EuclidMatrix)]
 #[repr(C)]
-pub struct TypedPoint3D<T, U> {
+pub struct Point3D<T, U> {
     pub x: T,
     pub y: T,
     pub z: T,
     #[doc(hidden)]
     pub _unit: PhantomData<U>,
 }
 
-mint_vec!(TypedPoint3D[x, y, z] = Point3);
+mint_vec!(Point3D[x, y, z] = Point3);
+
+impl<T: Copy, U> Copy for Point3D<T, U> {}
+
+impl<T: Clone, U> Clone for Point3D<T, U> {
+    fn clone(&self) -> Self {
+        Point3D {
+            x: self.x.clone(),
+            y: self.y.clone(),
+            z: self.z.clone(),
+            _unit: PhantomData,
+        }
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de, T, U> serde::Deserialize<'de> for Point3D<T, U>
+    where T: serde::Deserialize<'de>
+{
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where D: serde::Deserializer<'de>
+    {
+        let (x, y, z) = try!(serde::Deserialize::deserialize(deserializer));
+        Ok(Point3D { x, y, z, _unit: PhantomData })
+    }
+}
 
-/// Default 3d point type with no unit.
-///
-/// `Point3D` provides the same methods as `TypedPoint3D`.
-pub type Point3D<T> = TypedPoint3D<T, UnknownUnit>;
+#[cfg(feature = "serde")]
+impl<T, U> serde::Serialize for Point3D<T, U>
+    where T: serde::Serialize
+{
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+        where S: serde::Serializer
+    {
+        (&self.x, &self.y, &self.z).serialize(serializer)
+    }
+}
+
+impl<T, U> Eq for Point3D<T, U> where T: Eq {}
 
-impl<T: Copy + Zero, U> TypedPoint3D<T, U> {
+impl<T, U> PartialEq for Point3D<T, U>
+    where T: PartialEq
+{
+    fn eq(&self, other: &Self) -> bool {
+        self.x == other.x && self.y == other.y && self.z == other.z
+    }
+}
+
+impl<T, U> Hash for Point3D<T, U>
+    where T: Hash
+{
+    fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
+        self.x.hash(h);
+        self.y.hash(h);
+        self.z.hash(h);
+    }
+}
+
+impl<T: Copy + Zero, U> Point3D<T, U> {
     /// Constructor, setting all components to zero.
     #[inline]
     pub fn origin() -> Self {
         point3(Zero::zero(), Zero::zero(), Zero::zero())
     }
 
     #[inline]
     pub fn zero() -> Self {
         Self::origin()
     }
 }
 
-impl<T: Copy + One, U> TypedPoint3D<T, U> {
+impl<T: Copy + One, U> Point3D<T, U> {
     #[inline]
     pub fn to_array_4d(&self) -> [T; 4] {
         [self.x, self.y, self.z, One::one()]
     }
 
     #[inline]
     pub fn to_tuple_4d(&self) -> (T, T, T, T) {
         (self.x, self.y, self.z, One::one())
     }
 }
 
-impl<T, U> TypedPoint3D<T, U>
+impl<T, U> Point3D<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 {
@@ -490,203 +584,190 @@ where
         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> {
+impl<T: fmt::Debug, U> fmt::Debug for Point3D<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> {
+impl<T: fmt::Display, U> fmt::Display for Point3D<T, U> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "({},{},{})", self.x, self.y, self.z)
     }
 }
 
-impl<T: Copy + Default, U> Default for TypedPoint3D<T, U> {
+impl<T: Copy + Default, U> Default for Point3D<T, U> {
     fn default() -> Self {
-        TypedPoint3D::new(Default::default(), Default::default(), Default::default())
+        Point3D::new(Default::default(), Default::default(), Default::default())
     }
 }
 
-impl<T: Copy, U> TypedPoint3D<T, U> {
+impl<T: Copy, U> Point3D<T, U> {
     /// Constructor taking scalar values directly.
     #[inline]
     pub fn new(x: T, y: T, z: T) -> Self {
-        TypedPoint3D {
+        Point3D {
             x,
             y,
             z,
             _unit: PhantomData,
         }
     }
 
-    /// Constructor taking properly typed Lengths instead of scalar values.
+    /// Constructor taking properly  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)
+    pub fn to_vector(&self) -> Vector3D<T, U> {
+        Vector3D {
+            x: self.x,
+            y: self.y,
+            z: self.z,
+            _unit: PhantomData,
+        }
     }
 
     /// Returns a 2d point using this point's x and y coordinates
     #[inline]
-    pub fn xy(&self) -> TypedPoint2D<T, U> {
+    pub fn xy(&self) -> Point2D<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> {
+    pub fn xz(&self) -> Point2D<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> {
+    pub fn yz(&self) -> Point2D<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]
     }
 
     #[inline]
     pub fn to_tuple(&self) -> (T, T, T) {
         (self.x, self.y, self.z)
     }
 
     /// Drop the units, preserving only the numeric value.
     #[inline]
-    pub fn to_untyped(&self) -> Point3D<T> {
+    pub fn to_untyped(&self) -> Point3D<T, UnknownUnit> {
         point3(self.x, self.y, self.z)
     }
 
     /// Tag a unitless value with units.
     #[inline]
-    pub fn from_untyped(p: &Point3D<T>) -> Self {
+    pub fn from_untyped(p: Point3D<T, UnknownUnit>) -> Self {
         point3(p.x, p.y, p.z)
     }
 
     /// Convert into a 2d point.
     #[inline]
-    pub fn to_2d(&self) -> TypedPoint2D<T, U> {
+    pub fn to_2d(&self) -> Point2D<T, U> {
         self.xy()
     }
 }
 
-impl<T: Copy + Add<T, Output = T>, U> TypedPoint3D<T, U> {
+impl<T: Copy + Add<T, Output = T>, U> Point3D<T, U> {
     #[inline]
-    pub fn add_size(&self, other: &TypedSize3D<T, U>) -> Self {
+    pub fn add_size(&self, other: &Size3D<T, U>) -> Self {
         point3(self.x + other.width, self.y + other.height, self.z + other.depth)
     }
 }
 
-impl<T: Copy + Add<T, Output = T>, U> AddAssign<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+impl<T: Copy + Add<T, Output = T>, U> AddAssign<Vector3D<T, U>> for Point3D<T, U> {
     #[inline]
-    fn add_assign(&mut self, other: TypedVector3D<T, U>) {
+    fn add_assign(&mut self, other: Vector3D<T, U>) {
         *self = *self + other
     }
 }
 
-impl<T: Copy + Sub<T, Output = T>, U> SubAssign<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+impl<T: Copy + Sub<T, Output = T>, U> SubAssign<Vector3D<T, U>> for Point3D<T, U> {
     #[inline]
-    fn sub_assign(&mut self, other: TypedVector3D<T, U>) {
+    fn sub_assign(&mut self, other: Vector3D<T, U>) {
         *self = *self - other
     }
 }
 
-impl<T: Copy + Add<T, Output = T>, U> Add<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
+impl<T: Copy + Add<T, Output = T>, U> Add<Vector3D<T, U>> for Point3D<T, U> {
     type Output = Self;
     #[inline]
-    fn add(self, other: TypedVector3D<T, U>) -> Self {
+    fn add(self, other: Vector3D<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>;
+impl<T: Copy + Sub<T, Output = T>, U> Sub for Point3D<T, U> {
+    type Output = Vector3D<T, U>;
     #[inline]
-    fn sub(self, other: Self) -> TypedVector3D<T, U> {
+    fn sub(self, other: Self) -> Vector3D<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> {
+impl<T: Copy + Sub<T, Output = T>, U> Sub<Vector3D<T, U>> for Point3D<T, U> {
     type Output = Self;
     #[inline]
-    fn sub(self, other: TypedVector3D<T, U>) -> Self {
+    fn sub(self, other: Vector3D<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> {
+impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Point3D<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 + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedPoint3D<T, U1> {
-    type Output = TypedPoint3D<T, U2>;
+impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<Scale<T, U1, U2>> for Point3D<T, U1> {
+    type Output = Point3D<T, U2>;
     #[inline]
-    fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedPoint3D<T, U2> {
+    fn mul(self, scale: Scale<T, U1, U2>) -> Point3D<T, U2> {
         point3(self.x * scale.get(), self.y * scale.get(), self.z * scale.get())
     }
 }
 
-impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedPoint3D<T, U> {
+impl<T: Copy + Div<T, Output = T>, U> Div<T> for Point3D<T, U> {
     type Output = Self;
     #[inline]
     fn div(self, scale: T) -> Self {
         point3(self.x / scale, self.y / scale, self.z / scale)
     }
 }
 
-impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedPoint3D<T, U2> {
-    type Output = TypedPoint3D<T, U1>;
+impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Point3D<T, U2> {
+    type Output = Point3D<T, U1>;
     #[inline]
-    fn div(self, scale: TypedScale<T, U1, U2>) -> TypedPoint3D<T, U1> {
+    fn div(self, scale: Scale<T, U1, U2>) -> Point3D<T, U1> {
         point3(self.x / scale.get(), self.y / scale.get(), self.z / scale.get())
     }
 }
 
-impl<T: Float, U> TypedPoint3D<T, U> {
+impl<T: Float, U> Point3D<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),
         )
     }
@@ -701,133 +782,133 @@ impl<T: Float, U> TypedPoint3D<T, U> {
     }
 
     #[inline]
     pub fn clamp(&self, start: Self, end: Self) -> Self {
         self.max(start).min(end)
     }
 }
 
-impl<T: Round, U> TypedPoint3D<T, U> {
+impl<T: Round, U> Point3D<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)]
+    #[must_use]
     pub fn round(&self) -> Self {
         point3(self.x.round(), self.y.round(), self.z.round())
     }
 }
 
-impl<T: Ceil, U> TypedPoint3D<T, U> {
+impl<T: Ceil, U> Point3D<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)]
+    #[must_use]
     pub fn ceil(&self) -> Self {
         point3(self.x.ceil(), self.y.ceil(), self.z.ceil())
     }
 }
 
-impl<T: Floor, U> TypedPoint3D<T, U> {
+impl<T: Floor, U> Point3D<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)]
+    #[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> {
+impl<T: NumCast + Copy, U> Point3D<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> {
+    pub fn cast<NewT: NumCast + Copy>(&self) -> Point3D<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>> {
+    pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Point3D<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> {
+    pub fn to_f32(&self) -> Point3D<f32, U> {
         self.cast()
     }
 
     /// Cast into an `f64` point.
     #[inline]
-    pub fn to_f64(&self) -> TypedPoint3D<f64, U> {
+    pub fn to_f64(&self) -> Point3D<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> {
+    pub fn to_usize(&self) -> Point3D<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> {
+    pub fn to_u32(&self) -> Point3D<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> {
+    pub fn to_i32(&self) -> Point3D<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> {
+    pub fn to_i64(&self) -> Point3D<i64, U> {
         self.cast()
     }
 }
 
-impl<T: Copy + ApproxEq<T>, U> ApproxEq<TypedPoint3D<T, U>> for TypedPoint3D<T, U> {
+impl<T: Copy + ApproxEq<T>, U> ApproxEq<Point3D<T, U>> for Point3D<T, U> {
     #[inline]
     fn approx_epsilon() -> Self {
         point3(
             T::approx_epsilon(),
             T::approx_epsilon(),
             T::approx_epsilon(),
         )
     }
@@ -839,52 +920,66 @@ impl<T: Copy + ApproxEq<T>, U> ApproxEq<
 
     #[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> {
+impl<T: Copy, U> Into<[T; 3]> for Point3D<T, U> {
     fn into(self) -> [T; 3] {
         self.to_array()
     }
 }
 
-impl<T: Copy, U> From<[T; 3]> for TypedPoint3D<T, U> {
+impl<T: Copy, U> From<[T; 3]> for Point3D<T, U> {
     fn from(array: [T; 3]) -> Self {
         point3(array[0], array[1], array[2])
     }
 }
 
-impl<T: Copy, U> Into<(T, T, T)> for TypedPoint3D<T, U> {
+impl<T: Copy, U> Into<(T, T, T)> for Point3D<T, U> {
     fn into(self) -> (T, T, T) {
         self.to_tuple()
     }
 }
 
-impl<T: Copy, U> From<(T, T, T)> for TypedPoint3D<T, U> {
+impl<T: Copy, U> From<(T, T, T)> for Point3D<T, U> {
     fn from(tuple: (T, T, T)) -> Self {
         point3(tuple.0, tuple.1, tuple.2)
     }
 }
 
-pub fn point2<T: Copy, U>(x: T, y: T) -> TypedPoint2D<T, U> {
-    TypedPoint2D::new(x, y)
+#[inline]
+pub fn point2<T: Copy, U>(x: T, y: T) -> Point2D<T, U> {
+    Point2D {
+        x,
+        y,
+        _unit: PhantomData,
+    }
 }
 
-pub fn point3<T: Copy, U>(x: T, y: T, z: T) -> TypedPoint3D<T, U> {
-    TypedPoint3D::new(x, y, z)
+#[inline]
+pub fn point3<T: Copy, U>(x: T, y: T, z: T) -> Point3D<T, U> {
+    Point3D {
+        x,
+        y,
+        z,
+        _unit: PhantomData,
+    }
 }
 
 
 #[cfg(test)]
 mod point2d {
-    use super::Point2D;
+    use default::Point2D;
+    use {point2, vec2};
+    use scale::Scale;
+
     #[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;
@@ -916,29 +1011,22 @@ mod point2d {
     #[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>;
+    pub type Point2DMm<T> = super::Point2D<T, Mm>;
+    pub type Point2DCm<T> = super::Point2D<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;
 
@@ -949,29 +1037,27 @@ mod typedpoint2d {
     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() {
+    pub fn test_typed_scalar_mul() {
         let p1 = Point2DMm::new(1.0, 2.0);
-        let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
+        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::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);
         }
     }
@@ -980,17 +1066,19 @@ mod typedpoint2d {
     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};
+    use default;
+    use default::Point3D;
+    use {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);
 
@@ -1019,25 +1107,24 @@ mod point3d {
             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);
+        let p: default::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);
     }
-
 }
--- a/third_party/rust/euclid/src/rect.rs
+++ b/third_party/rust/euclid/src/rect.rs
@@ -3,145 +3,133 @@
 //
 // 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 scale::Scale;
 use num::*;
-use box2d::TypedBox2D;
-use point::TypedPoint2D;
-use vector::TypedVector2D;
-use side_offsets::TypedSideOffsets2D;
-use size::TypedSize2D;
+use box2d::Box2D;
+use point::Point2D;
+use vector::Vector2D;
+use side_offsets::SideOffsets2D;
+use size::Size2D;
 use approxord::{min, max};
+use nonempty::NonEmpty;
 
 use num_traits::NumCast;
 #[cfg(feature = "serde")]
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use serde::{Deserialize, Serialize};
 
 use core::borrow::Borrow;
 use core::cmp::PartialOrd;
 use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::ops::{Add, Div, Mul, Sub, Range};
 
 
 /// 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>,
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
+pub struct Rect<T, U> {
+    pub origin: Point2D<T, U>,
+    pub size: Size2D<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> {
+impl<T: Hash, U> Hash for Rect<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> Copy for Rect<T, U> {}
 
-impl<T: Copy, U> Clone for TypedRect<T, U> {
+impl<T: Copy, U> Clone for Rect<T, U> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-impl<T: PartialEq, U> PartialEq<TypedRect<T, U>> for TypedRect<T, U> {
+impl<T: PartialEq, U> PartialEq<Rect<T, U>> for Rect<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: Eq, U> Eq for Rect<T, U> {}
 
-impl<T: fmt::Debug, U> fmt::Debug for TypedRect<T, U> {
+impl<T: fmt::Debug, U> fmt::Debug for Rect<T, U> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypedRect({:?} at {:?})", self.size, self.origin)
+        write!(f, "Rect({:?} at {:?})", self.size, self.origin)
     }
 }
 
-impl<T: fmt::Display, U> fmt::Display for TypedRect<T, U> {
+impl<T: fmt::Display, U> fmt::Display for Rect<T, U> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "Rect({} at {})", self.size, self.origin)
     }
 }
 
-impl<T: Default, U> Default for TypedRect<T, U> {
+impl<T: Default, U> Default for Rect<T, U> {
     fn default() -> Self {
-        TypedRect::new(Default::default(), Default::default())
+        Rect::new(Default::default(), Default::default())
     }
 }
 
-impl<T, U> TypedRect<T, U> {
+impl<T, U> Rect<T, U> {
     /// Constructor.
-    pub fn new(origin: TypedPoint2D<T, U>, size: TypedSize2D<T, U>) -> Self {
-        TypedRect {
+    pub fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
+        Rect {
             origin,
             size,
         }
     }
 }
 
-impl<T, U> TypedRect<T, U>
+impl<T, U> Rect<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(),
+    pub fn from_size(size: Size2D<T, U>) -> Self {
+        Rect {
+            origin: Point2D::zero(),
             size,
         }
     }
 }
 
-impl<T, U> TypedRect<T, U>
+impl<T, U> Rect<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 min(&self) -> Point2D<T, U> {
+        self.origin
+    }
+
+    #[inline]
+    pub fn max(&self) -> Point2D<T, U> {
+        self.origin + self.size
+    }
+
+    #[inline]
     pub fn max_x(&self) -> T {
         self.origin.x + self.size.width
     }
 
     #[inline]
     pub fn min_x(&self) -> T {
         self.origin.x
     }
@@ -152,167 +140,122 @@ where
     }
 
     #[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 x_range(&self) -> Range<T> {
         self.min_x()..self.max_x()
     }
 
     #[inline]
     pub fn y_range(&self) -> Range<T> {
         self.min_y()..self.max_y()
     }
 
     #[inline]
     pub fn intersection(&self, other: &Self) -> Option<Self> {
         if !self.intersects(other) {
             return None;
         }
 
-        let upper_left = TypedPoint2D::new(
+        let upper_left = Point2D::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(
+        Some(Rect::new(
             upper_left,
-            TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
+            Size2D::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)
+    #[must_use]
+    pub fn translate(&self, by: Vector2D<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 {
+    pub fn contains(&self, other: Point2D<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()
+        rect.is_empty_or_negative()
             || (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)]
+    #[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(
+        Rect::new(
+            Point2D::new(self.origin.x - width, self.origin.y - height),
+            Size2D::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]
-    pub fn to_box2d(&self) -> TypedBox2D<T, U> {
-        TypedBox2D {
-            min: self.origin,
-            max: self.bottom_right(),
+    pub fn to_box2d(&self) -> Box2D<T, U> {
+        Box2D {
+            min: self.min(),
+            max: self.max(),
         }
     }
 
-    #[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(
+    /// This method assumes y oriented downward.
+    pub fn inner_rect(&self, offsets: SideOffsets2D<T, U>) -> Self {
+        let rect = Rect::new(
+            Point2D::new(
                 self.origin.x + offsets.left,
                 self.origin.y + offsets.top
             ),
-            TypedSize2D::new(
+            Size2D::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(
+    /// This method assumes y oriented downward.
+    pub fn outer_rect(&self, offsets: SideOffsets2D<T, U>) -> Self {