servo: Merge #17184 - Bump euclid to 0.14.x (from nical:euclid-bump); r=SimonSapin
authorNicolas Silva <nical@fastmail.com>
Wed, 14 Jun 2017 07:25:05 -0700
changeset 412632 c335572b2dc164ab46193733f7bcc159b435d16b
parent 412631 f23dc18a0316fd3d2abf18cab056aa3ad2ef70c7
child 412633 0112e92d67d3c90a82ed7f2a6d8e5454b492df74
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersSimonSapin
milestone56.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
servo: Merge #17184 - Bump euclid to 0.14.x (from nical:euclid-bump); r=SimonSapin - [x] `./mach build -d` does not report any errors (kinda, need webrender published and Cargo.toml fixed up) - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because it is a refactoring in which the difference is mostly a compile-time/strong-typing thing with no change to the logic. Source-Repo: https://github.com/servo/servo Source-Revision: 18653f69581693a5bae1ce4e350e78bc16159b08
servo/Cargo.lock
servo/components/canvas/Cargo.toml
servo/components/canvas/canvas_paint_thread.rs
servo/components/canvas/webgl_paint_thread.rs
servo/components/canvas_traits/Cargo.toml
servo/components/canvas_traits/lib.rs
servo/components/compositing/Cargo.toml
servo/components/compositing/compositor.rs
servo/components/compositing/compositor_thread.rs
servo/components/compositing/lib.rs
servo/components/compositing/touch.rs
servo/components/compositing/windowing.rs
servo/components/config/Cargo.toml
servo/components/config/opts.rs
servo/components/constellation/Cargo.toml
servo/components/constellation/browsingcontext.rs
servo/components/constellation/constellation.rs
servo/components/constellation/pipeline.rs
servo/components/geometry/Cargo.toml
servo/components/geometry/lib.rs
servo/components/gfx/Cargo.toml
servo/components/gfx/display_list/mod.rs
servo/components/gfx/text/glyph.rs
servo/components/layout/Cargo.toml
servo/components/layout/block.rs
servo/components/layout/display_list_builder.rs
servo/components/layout/flow.rs
servo/components/layout/fragment.rs
servo/components/layout/inline.rs
servo/components/layout/list_item.rs
servo/components/layout/model.rs
servo/components/layout/multicol.rs
servo/components/layout/query.rs
servo/components/layout/sequential.rs
servo/components/layout/webrender_helpers.rs
servo/components/layout_thread/Cargo.toml
servo/components/layout_thread/lib.rs
servo/components/script/Cargo.toml
servo/components/script/dom/bindings/trace.rs
servo/components/script/dom/canvaspattern.rs
servo/components/script/dom/canvasrenderingcontext2d.rs
servo/components/script/dom/document.rs
servo/components/script/dom/dommatrix.rs
servo/components/script/dom/dommatrixreadonly.rs
servo/components/script/dom/eventsource.rs
servo/components/script/dom/htmlareaelement.rs
servo/components/script/dom/htmlcanvaselement.rs
servo/components/script/dom/htmlimageelement.rs
servo/components/script/dom/imagedata.rs
servo/components/script/dom/node.rs
servo/components/script/dom/webglrenderingcontext.rs
servo/components/script/dom/window.rs
servo/components/script/dom/xmlhttprequest.rs
servo/components/script/script_thread.rs
servo/components/script/timers.rs
servo/components/script/webdriver_handlers.rs
servo/components/script_layout_interface/Cargo.toml
servo/components/script_layout_interface/message.rs
servo/components/script_layout_interface/rpc.rs
servo/components/script_traits/Cargo.toml
servo/components/script_traits/lib.rs
servo/components/script_traits/script_msg.rs
servo/components/script_traits/webdriver_msg.rs
servo/components/servo/Cargo.toml
servo/components/style/Cargo.toml
servo/components/style/animation.rs
servo/components/style/bezier.rs
servo/components/style/gecko_bindings/sugar/ns_timing_function.rs
servo/components/style/logical_geometry.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/length.rs
servo/components/style_traits/Cargo.toml
servo/components/style_traits/viewport.rs
servo/components/webdriver_server/Cargo.toml
servo/ports/cef/Cargo.toml
servo/ports/cef/browser_host.rs
servo/ports/cef/window.rs
servo/ports/glutin/Cargo.toml
servo/ports/glutin/window.rs
servo/python/tidy/servo_tidy_tests/rust_tidy.rs
servo/tests/unit/script/Cargo.toml
servo/tests/unit/script/htmlareaelement.rs
servo/tests/unit/style/Cargo.toml
servo/tests/unit/style/media_queries.rs
servo/tests/unit/style/parsing/mod.rs
servo/tests/unit/style/viewport.rs
servo/tests/unit/stylo/Cargo.toml
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -104,29 +104,29 @@ source = "registry+https://github.com/ru
 dependencies = [
  "mp3-metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "mp4parse 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "azure"
-version = "0.16.0"
-source = "git+https://github.com/servo/rust-azure#9db3ca5dde15c16f3a9b84c9099797a3f1a2eb00"
+version = "0.17.0"
+source = "git+https://github.com/servo/rust-azure#3944a65fd2a3790c85e3770d5130e1b4ab153b68"
 dependencies = [
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-skia 0.30000004.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-skia 0.30000005.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "backtrace"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -307,35 +307,35 @@ source = "registry+https://github.com/ru
 name = "bytes"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "canvas"
 version = "0.0.1"
 dependencies = [
- "azure 0.16.0 (git+https://github.com/servo/rust-azure)",
+ "azure 0.17.0 (git+https://github.com/servo/rust-azure)",
  "canvas_traits 0.0.1",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "webrender_traits 0.40.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.40.0 (git+https://github.com/servo/webrender)",
 ]
 
@@ -458,17 +458,17 @@ dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "compositing"
 version = "0.0.1"
 dependencies = [
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
@@ -489,29 +489,29 @@ dependencies = [
  "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
  "canvas 0.0.1",
  "canvas_traits 0.0.1",
  "clipboard 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "compositing 0.0.1",
  "debugger 0.0.1",
  "devtools_traits 0.0.1",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gaol 0.0.1 (git+https://github.com/servo/gaol)",
  "gfx 0.0.1",
  "gfx_traits 0.0.1",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "layout_traits 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net 0.0.1",
  "net_traits 0.0.1",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_rand 0.0.1",
  "servo_remutex 0.0.1",
  "servo_url 0.0.1",
@@ -569,29 +569,29 @@ dependencies = [
 name = "cssparser"
 version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "dbghelp-sys"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -743,17 +743,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "embedding"
 version = "0.0.1"
 dependencies = [
  "cocoa 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "compositing 0.0.1",
  "devtools 0.0.1",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "glutin_app 0.0.1",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "libservo 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -892,23 +892,22 @@ name = "error-chain"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "euclid"
-version = "0.13.0"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "expat-sys"
 version = "2.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1028,17 +1027,17 @@ version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "harfbuzz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1123,17 +1122,17 @@ version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "glutin_app"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "compositing 0.0.1",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "osmesa-src 12.0.1 (git+https://github.com/servo/osmesa-src)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
@@ -1414,17 +1413,17 @@ source = "registry+https://github.com/ru
 [[package]]
 name = "layout"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx 0.0.1",
  "gfx_traits 0.0.1",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1460,17 +1459,17 @@ dependencies = [
  "size_of_test 0.0.1",
 ]
 
 [[package]]
 name = "layout_thread"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx 0.0.1",
  "gfx_traits 0.0.1",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "layout 0.0.1",
  "layout_traits 0.0.1",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1554,17 +1553,17 @@ dependencies = [
  "canvas 0.0.1",
  "canvas_traits 0.0.1",
  "compositing 0.0.1",
  "constellation 0.0.1",
  "debugger 0.0.1",
  "devtools 0.0.1",
  "devtools_traits 0.0.1",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gaol 0.0.1 (git+https://github.com/servo/gaol)",
  "gfx 0.0.1",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "layout_thread 0.0.1",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net 0.0.1",
@@ -1941,22 +1940,22 @@ dependencies = [
 
 [[package]]
 name = "odds"
 version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "offscreen_gl_context"
-version = "0.8.10"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gl_generator 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2116,21 +2115,21 @@ dependencies = [
 
 [[package]]
 name = "pkg-config"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "plane-split"
-version = "0.4.0"
+version = "0.5.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.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "plugin_compiletest"
 version = "0.0.1"
 dependencies = [
@@ -2153,17 +2152,17 @@ dependencies = [
 
 [[package]]
 name = "precomputed-hash"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "procedural-masquerade"
-version = "0.1.2"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "profile"
 version = "0.0.1"
 dependencies = [
  "heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2372,17 +2371,17 @@ dependencies = [
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "deny_public_fields 0.0.1",
  "devtools_traits 0.0.1",
  "dom_struct 0.0.1",
  "domobject_derive 0.0.1",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2394,17 +2393,17 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "profile_traits 0.0.1",
  "range 0.0.1",
  "ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2440,17 +2439,17 @@ dependencies = [
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "canvas_traits 0.0.1",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
@@ -2467,42 +2466,42 @@ dependencies = [
 [[package]]
 name = "script_plugins"
 version = "0.0.1"
 
 [[package]]
 name = "script_tests"
 version = "0.0.1"
 dependencies = [
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "script 0.0.1",
  "servo_url 0.0.1",
 ]
 
 [[package]]
 name = "script_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
  "canvas_traits 0.0.1",
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "devtools_traits 0.0.1",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper_serde 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "profile_traits 0.0.1",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_atoms 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2650,22 +2649,22 @@ dependencies = [
  "shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11-dl 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "servo-skia"
-version = "0.30000004.3"
+version = "0.30000005.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cgl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "expat-sys 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "io-surface 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-fontconfig-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2707,17 +2706,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "servo_config"
 version = "0.0.1"
 dependencies = [
  "android_injected_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_geometry 0.0.1",
@@ -2733,17 +2732,17 @@ dependencies = [
  "servo_config 0.0.1",
 ]
 
 [[package]]
 name = "servo_geometry"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "servo_rand"
 version = "0.0.1"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2895,17 +2894,17 @@ dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bindgen 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2948,17 +2947,17 @@ dependencies = [
 
 [[package]]
 name = "style_tests"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_atoms 0.0.1",
  "servo_config 0.0.1",
  "servo_url 0.0.1",
@@ -2969,32 +2968,32 @@ dependencies = [
 
 [[package]]
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "size_of_test 0.0.1",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
@@ -3328,17 +3327,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "webdriver_server"
 version = "0.0.1"
 dependencies = [
  "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3348,58 +3347,58 @@ dependencies = [
  "url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
 version = "0.40.0"
-source = "git+https://github.com/servo/webrender#caec344131e53c13b022feedbf9d5e04054232c3"
+source = "git+https://github.com/servo/webrender#faed91dd24e695b8c7c555ef3398d0ba8fd165dc"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gamma-lut 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "plane-split 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_traits 0.40.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_traits"
 version = "0.40.0"
-source = "git+https://github.com/servo/webrender#caec344131e53c13b022feedbf9d5e04054232c3"
+source = "git+https://github.com/servo/webrender#faed91dd24e695b8c7c555ef3398d0ba8fd165dc"
 dependencies = [
  "app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webvr"
 version = "0.0.1"
@@ -3523,17 +3522,17 @@ dependencies = [
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
 "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
 "checksum app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b03f9404bb507e374418345f5ebeef57b32c35e8cb3c36e58a7d0b73fd063c77"
 "checksum arraydeque 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "96e774cadb24c2245225280c6799793f9802b918a58a79615e9490607489a717"
 "checksum arrayvec 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "699e63a93b79d717e8c3b5eb1b28b7780d0d6d9e59a72eb769291c83b0c8dc67"
 "checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum audio-video-metadata 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3b6ef29ee98ad95a37f34547fd7fb40724772294110ed6ca0445fc2e964c29d1"
-"checksum azure 0.16.0 (git+https://github.com/servo/rust-azure)" = "<none>"
+"checksum azure 0.17.0 (git+https://github.com/servo/rust-azure)" = "<none>"
 "checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
 "checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff"
 "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0-alpha6 (registry+https://github.com/rust-lang/crates.io-index)" = "fb0cdeac1c5d567fdb487ae5853c024e4acf1ea85ba6a6552fe084e0805fea5d"
 "checksum bindgen 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e28791695e6e29a82038bd0489a760f362157dc1a3b2bbac9b6be3ddd984ff7"
 "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
 "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
@@ -3590,17 +3589,17 @@ dependencies = [
 "checksum energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)" = "<none>"
 "checksum energymon-builder 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "<none>"
 "checksum energymon-default-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "<none>"
 "checksum energymon-sys 0.3.0 (git+https://github.com/energymon/energymon-sys.git)" = "<none>"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum error-chain 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "318cb3c71ee4cdea69fdc9e15c173b245ed6063e1709029e8fd32525a881120f"
-"checksum euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6083f113c422ff9cd855a1cf6cc8ec0903606c0eb43a0c6a0ced3bdc9731e4c1"
+"checksum euclid 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995b21c36b37e0f18ed9ba1714378a337e3ff19a6e5e952ea94b0f3dd4e12fbc"
 "checksum expat-sys 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cef36cd1a8a02d28b91d97347c63247b9e4cb8a8e36df36f8201dc87a1c0859c"
 "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum fontsan 0.3.2 (git+https://github.com/servo/fontsan)" = "<none>"
 "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
 "checksum freetype 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fde23272c687e4570aefec06cb71174ec0f5284b725deac4e77ba2665d635faf"
 "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
 "checksum futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "55f0008e13fc853f79ea8fc86e931486860d4c4c156cdffb59fa5f7fa833660a"
@@ -3670,17 +3669,17 @@ dependencies = [
 "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
 "checksum num-rational 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c2dc5ea04020a8f18318ae485c751f8cfa1c0e69dcf465c29ddaaa64a313cc44"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
 "checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e"
 "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
 "checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297"
 "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
-"checksum offscreen_gl_context 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)" = "848e08e715273079e73c5538632bb3bf84aadcb9e754fcf690da1b054889770b"
+"checksum offscreen_gl_context 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f2b1feeb87a68541c96e07b8b81a3fef0057b026b5f691b4489852811e76804"
 "checksum ogg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7137bf02687385302f4c0aecd77cfce052b69f5b4ee937be778e125c62f67e30"
 "checksum ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc665717454399cba557c55ad226148996e9266ee291f8a37a98bb2cded0a490"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
 "checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2"
 "checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897"
 "checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"
 "checksum osmesa-src 12.0.1 (git+https://github.com/servo/osmesa-src)" = "<none>"
 "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
@@ -3690,20 +3689,20 @@ dependencies = [
 "checksum parse-hosts 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7626e29ef8f479f10d9a753f1fca914506663ecc9ec2dedb8cffc610a3d1f705"
 "checksum pdqsort 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ceca1642c89148ca05611cc775a0c383abef355fc4907c4e95f49f7b09d6287c"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "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 plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "556929ef77bf07a9f8584d21382bcebcd6e6f5845d311824d369e1df7cf56d54"
+"checksum plane-split 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da4c13e9ba1388fd628ec2bcd69f3346dec64357e9b552601b244f92189d4610"
 "checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82"
 "checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150"
-"checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
+"checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
 "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
 "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a"
 "checksum rayon-core 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd1e76f8ee0322fbbeb0c43a07e1757fcf8ff06bb0ff92da017625882ddc04dd"
 "checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b"
@@ -3722,17 +3721,17 @@ dependencies = [
 "checksum serde_codegen_internals 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc888bd283bd2420b16ad0d860e35ad8acb21941180a83a189bb2046f9d00400"
 "checksum serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "978fd866f4d4872084a81ccc35e275158351d3b9fe620074e7d7504b816b74ba"
 "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
 "checksum servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21069a884c33fe6ee596975e1f3849ed88c4ec857fbaf11d33672d8ebe051217"
 "checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
 "checksum servo-fontconfig-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6be80777ee6edecbbbf8774c76e19dddfe336256c57a4ded06d6ad3df7be358e"
 "checksum servo-freetype-sys 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
 "checksum servo-glutin 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8398095f9b3dc3c6d706d395e192624be1f1bcc6f366b009fe17a20cb5dd3d72"
-"checksum servo-skia 0.30000004.3 (registry+https://github.com/rust-lang/crates.io-index)" = "109e567850bad212ee98ed9651e256de862bd9764476f2b16355af5f6ef59cfe"
+"checksum servo-skia 0.30000005.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3047c224334358fd376b04b83454a7e9f5473c131c3e24db156a99251e495e3c"
 "checksum servo-websocket 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ff13c5d852c2793805226e688044309f2c1d8f063784805a13e99cb75b611"
 "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
 "checksum shared_library 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb04126b6fcfd2710fb5b6d18f4207b6c535f2850a7e1a43bcd526d44f30a79a"
 "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d"
 "checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5"
 "checksum signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)" = "<none>"
 "checksum simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
--- a/servo/components/canvas/Cargo.toml
+++ b/servo/components/canvas/Cargo.toml
@@ -8,16 +8,16 @@ publish = false
 [lib]
 name = "canvas"
 path = "lib.rs"
 
 [dependencies]
 azure = {git = "https://github.com/servo/rust-azure"}
 canvas_traits = {path = "../canvas_traits"}
 cssparser = "0.14.0"
-euclid = "0.13"
+euclid = "0.14.4"
 gleam = "0.4"
 ipc-channel = "0.7"
 log = "0.3.5"
 num-traits = "0.1.32"
-offscreen_gl_context = "0.8"
+offscreen_gl_context = { version = "0.9", features = ["serde"] }
 servo_config = {path = "../config"}
 webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas/canvas_paint_thread.rs
+++ b/servo/components/canvas/canvas_paint_thread.rs
@@ -5,20 +5,17 @@
 use azure::azure::AzFloat;
 use azure::azure_hl::{AntialiasMode, CapStyle, CompositionOp, JoinStyle};
 use azure::azure_hl::{BackendType, DrawOptions, DrawTarget, Pattern, StrokeOptions, SurfaceFormat};
 use azure::azure_hl::{Color, ColorPattern, DrawSurfaceOptions, Filter, PathBuilder};
 use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern};
 use azure::azure_hl::SurfacePattern;
 use canvas_traits::*;
 use cssparser::RGBA;
-use euclid::matrix2d::Matrix2D;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
 use ipc_channel::ipc::{self, IpcSender};
 use num_traits::ToPrimitive;
 use std::borrow::ToOwned;
 use std::mem;
 use std::sync::Arc;
 use std::thread;
 use webrender_traits;
 
@@ -66,17 +63,17 @@ pub struct CanvasPaintThread<'a> {
 
 #[derive(Clone)]
 struct CanvasPaintState<'a> {
     draw_options: DrawOptions,
     fill_style: Pattern,
     stroke_style: Pattern,
     stroke_opts: StrokeOptions<'a>,
     /// The current 2D transform matrix.
-    transform: Matrix2D<f32>,
+    transform: Transform2D<f32>,
     shadow_offset_x: f64,
     shadow_offset_y: f64,
     shadow_blur: f64,
     shadow_color: Color,
 }
 
 impl<'a> CanvasPaintState<'a> {
     fn new(antialias: bool) -> CanvasPaintState<'a> {
@@ -86,17 +83,17 @@ impl<'a> CanvasPaintState<'a> {
             AntialiasMode::None
         };
 
         CanvasPaintState {
             draw_options: DrawOptions::new(1.0, CompositionOp::Over, antialias),
             fill_style: Pattern::Color(ColorPattern::new(Color::black())),
             stroke_style: Pattern::Color(ColorPattern::new(Color::black())),
             stroke_opts: StrokeOptions::new(1.0, JoinStyle::MiterOrBevel, CapStyle::Butt, 10.0, &[]),
-            transform: Matrix2D::identity(),
+            transform: Transform2D::identity(),
             shadow_offset_x: 0.0,
             shadow_offset_y: 0.0,
             shadow_blur: 0.0,
             shadow_color: Color::transparent(),
         }
     }
 }
 
@@ -523,17 +520,17 @@ impl<'a> CanvasPaintThread<'a> {
     fn set_line_join(&mut self, join: LineJoinStyle) {
         self.state.stroke_opts.line_join = join.to_azure_style();
     }
 
     fn set_miter_limit(&mut self, limit: f32) {
         self.state.stroke_opts.miter_limit = limit;
     }
 
-    fn set_transform(&mut self, transform: &Matrix2D<f32>) {
+    fn set_transform(&mut self, transform: &Transform2D<f32>) {
         self.state.transform = transform.clone();
         self.drawtarget.set_transform(transform)
     }
 
     fn set_global_alpha(&mut self, alpha: f32) {
         self.state.draw_options.alpha = alpha;
     }
 
@@ -601,17 +598,17 @@ impl<'a> CanvasPaintThread<'a> {
 
         // bgra -> rgba
         byte_swap(&mut dest_data);
         chan.send(dest_data).unwrap();
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
     fn put_image_data(&mut self, imagedata: Vec<u8>,
-                      offset: Point2D<f64>,
+                      offset: Vector2D<f64>,
                       image_data_size: Size2D<f64>,
                       mut dirty_rect: Rect<f64>) {
         if image_data_size.width <= 0.0 || image_data_size.height <= 0.0 {
             return
         }
 
         assert!(image_data_size.width * image_data_size.height * 4.0 == imagedata.len() as f64);
 
@@ -715,36 +712,35 @@ impl<'a> CanvasPaintThread<'a> {
          self.state.shadow_offset_y != 0.0f64 ||
          self.state.shadow_blur != 0.0f64)
     }
 
     fn create_draw_target_for_shadow(&self, source_rect: &Rect<f32>) -> DrawTarget {
         let draw_target = self.drawtarget.create_similar_draw_target(&Size2D::new(source_rect.size.width as i32,
                                                                                   source_rect.size.height as i32),
                                                                      self.drawtarget.get_format());
-        let matrix = Matrix2D::identity()
-            .pre_translated(-source_rect.origin.x as AzFloat,
-                            -source_rect.origin.y as AzFloat)
+        let matrix = Transform2D::identity()
+            .pre_translate(-source_rect.origin.to_vector().cast().unwrap())
             .pre_mul(&self.state.transform);
         draw_target.set_transform(&matrix);
         draw_target
     }
 
     fn draw_with_shadow<F>(&self, rect: &Rect<f32>, draw_shadow_source: F)
         where F: FnOnce(&DrawTarget)
     {
         let shadow_src_rect = self.state.transform.transform_rect(rect);
         let new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect);
         draw_shadow_source(&new_draw_target);
         self.drawtarget.draw_surface_with_shadow(new_draw_target.snapshot(),
                                                  &Point2D::new(shadow_src_rect.origin.x as AzFloat,
                                                                shadow_src_rect.origin.y as AzFloat),
                                                  &self.state.shadow_color,
-                                                 &Point2D::new(self.state.shadow_offset_x as AzFloat,
-                                                               self.state.shadow_offset_y as AzFloat),
+                                                 &Vector2D::new(self.state.shadow_offset_x as AzFloat,
+                                                                self.state.shadow_offset_y as AzFloat),
                                                  (self.state.shadow_blur / 2.0f64) as AzFloat,
                                                  self.state.draw_options.composition);
     }
 }
 
 impl<'a> Drop for CanvasPaintThread<'a> {
     fn drop(&mut self) {
         if let Some(image_key) = self.image_key {
@@ -996,44 +992,44 @@ impl ToAzurePattern for FillOrStrokeStyl
                         color: s.color.to_azure_style()
                     }
                 }).collect();
 
                 Some(Pattern::LinearGradient(LinearGradientPattern::new(
                     &Point2D::new(linear_gradient_style.x0 as AzFloat, linear_gradient_style.y0 as AzFloat),
                     &Point2D::new(linear_gradient_style.x1 as AzFloat, linear_gradient_style.y1 as AzFloat),
                     drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
-                    &Matrix2D::identity())))
+                    &Transform2D::identity())))
             },
             FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
                 let gradient_stops: Vec<GradientStop> = radial_gradient_style.stops.iter().map(|s| {
                     GradientStop {
                         offset: s.offset as AzFloat,
                         color: s.color.to_azure_style()
                     }
                 }).collect();
 
                 Some(Pattern::RadialGradient(RadialGradientPattern::new(
                     &Point2D::new(radial_gradient_style.x0 as AzFloat, radial_gradient_style.y0 as AzFloat),
                     &Point2D::new(radial_gradient_style.x1 as AzFloat, radial_gradient_style.y1 as AzFloat),
                     radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat,
                     drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
-                    &Matrix2D::identity())))
+                    &Transform2D::identity())))
             },
             FillOrStrokeStyle::Surface(ref surface_style) => {
                 drawtarget.create_source_surface_from_data(&surface_style.surface_data,
                                                            surface_style.surface_size,
                                                            surface_style.surface_size.width * 4,
                                                            SurfaceFormat::B8G8R8A8)
                           .map(|source_surface| {
                     Pattern::Surface(SurfacePattern::new(
                         source_surface.azure_source_surface,
                         surface_style.repeat_x,
                         surface_style.repeat_y,
-                        &Matrix2D::identity()))
+                        &Transform2D::identity()))
                     })
             }
         }
     }
 }
 
 impl ToAzureStyle for RGBA {
     type Target = Color;
--- a/servo/components/canvas/webgl_paint_thread.rs
+++ b/servo/components/canvas/webgl_paint_thread.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 canvas_traits::{CanvasCommonMsg, CanvasData, CanvasMsg, CanvasImageData};
 use canvas_traits::{FromLayoutMsg, FromScriptMsg, byte_swap};
-use euclid::size::Size2D;
+use euclid::Size2D;
 use gleam::gl;
 use ipc_channel::ipc::{self, IpcSender};
 use offscreen_gl_context::{ColorAttachmentType, GLContext, GLLimits};
 use offscreen_gl_context::{GLContextAttributes, NativeGLContext, OSMesaContext};
 use servo_config::opts;
 use std::borrow::ToOwned;
 use std::sync::Arc;
 use std::sync::mpsc::channel;
--- a/servo/components/canvas_traits/Cargo.toml
+++ b/servo/components/canvas_traits/Cargo.toml
@@ -6,15 +6,15 @@ license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "canvas_traits"
 path = "lib.rs"
 
 [dependencies]
 cssparser = "0.14.0"
-euclid = "0.13"
+euclid = "0.14.4"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 ipc-channel = "0.7"
 serde = "0.9"
 serde_derive = "0.9"
 webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]}
--- a/servo/components/canvas_traits/lib.rs
+++ b/servo/components/canvas_traits/lib.rs
@@ -11,20 +11,17 @@ extern crate cssparser;
 extern crate euclid;
 extern crate heapsize;
 #[macro_use] extern crate heapsize_derive;
 extern crate ipc_channel;
 #[macro_use] extern crate serde_derive;
 extern crate webrender_traits;
 
 use cssparser::RGBA;
-use euclid::matrix2d::Matrix2D;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D};
 use ipc_channel::ipc::IpcSender;
 use std::default::Default;
 use std::str::FromStr;
 use webrender_traits::{WebGLCommand, WebGLContextId, VRCompositorCommand};
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum FillRule {
     Nonzero,
@@ -82,32 +79,32 @@ pub enum Canvas2dMsg {
     Clip,
     ClosePath,
     Fill,
     FillRect(Rect<f32>),
     GetImageData(Rect<i32>, Size2D<f64>, IpcSender<Vec<u8>>),
     IsPointInPath(f64, f64, FillRule, IpcSender<bool>),
     LineTo(Point2D<f32>),
     MoveTo(Point2D<f32>),
-    PutImageData(Vec<u8>, Point2D<f64>, Size2D<f64>, Rect<f64>),
+    PutImageData(Vec<u8>, Vector2D<f64>, Size2D<f64>, Rect<f64>),
     QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
     Rect(Rect<f32>),
     RestoreContext,
     SaveContext,
     StrokeRect(Rect<f32>),
     Stroke,
     SetFillStyle(FillOrStrokeStyle),
     SetStrokeStyle(FillOrStrokeStyle),
     SetLineWidth(f32),
     SetLineCap(LineCapStyle),
     SetLineJoin(LineJoinStyle),
     SetMiterLimit(f32),
     SetGlobalAlpha(f32),
     SetGlobalComposition(CompositionOrBlending),
-    SetTransform(Matrix2D<f32>),
+    SetTransform(Transform2D<f32>),
     SetShadowOffsetX(f64),
     SetShadowOffsetY(f64),
     SetShadowBlur(f64),
     SetShadowColor(RGBA),
 }
 
 #[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct CanvasGradientStop {
--- a/servo/components/compositing/Cargo.toml
+++ b/servo/components/compositing/Cargo.toml
@@ -5,17 +5,17 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "compositing"
 path = "lib.rs"
 
 [dependencies]
-euclid = "0.13"
+euclid = "0.14"
 gfx_traits = {path = "../gfx_traits"}
 gleam = "0.4"
 image = "0.12"
 ipc-channel = "0.7"
 log = "0.3.5"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 profile_traits = {path = "../profile_traits"}
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -2,21 +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 CompositionPipeline;
 use SendableFrameTree;
 use compositor_thread::{CompositorProxy, CompositorReceiver};
 use compositor_thread::{InitialCompositorState, Msg, RenderListener};
 use delayed_composition::DelayedCompositionTimerProxy;
-use euclid::Point2D;
-use euclid::point::TypedPoint2D;
-use euclid::rect::TypedRect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::TypedSize2D;
+use euclid::{Point2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
 use gfx_traits::Epoch;
 use gleam::gl;
 use image::{DynamicImage, ImageFormat, RgbImage};
 use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, CONTROL};
 use msg::constellation_msg::{PipelineId, PipelineIndex, PipelineNamespaceId, TraversalDirection};
 use net_traits::image::base::{Image, PixelFormat};
 use profile_traits::time::{self, ProfilerCategory, profile};
@@ -34,17 +30,17 @@ use std::fs::File;
 use std::rc::Rc;
 use std::sync::mpsc::Sender;
 use std::time::{Duration, Instant};
 use style_traits::{CSSPixel, PinchZoomFactor};
 use style_traits::viewport::ViewportConstraints;
 use time::{precise_time_ns, precise_time_s};
 use touch::{TouchHandler, TouchAction};
 use webrender;
-use webrender_traits::{self, ClipId, LayoutPoint, ScrollEventPhase, ScrollLocation, ScrollClamping};
+use webrender_traits::{self, ClipId, LayoutPoint, LayoutVector2D, ScrollEventPhase, ScrollLocation, ScrollClamping};
 use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
 
 #[derive(Debug, PartialEq)]
 enum UnableToComposite {
     WindowUnprepared,
     NotReadyToPaintImage(NotReadyToPaint),
 }
 
@@ -1004,28 +1000,30 @@ impl<Window: WindowMethods> IOCompositor
                                                     identifier,
                                                     translated_point));
     }
 
     fn on_touch_move(&mut self, identifier: TouchId, point: TypedPoint2D<f32, DevicePixel>) {
         match self.touch_handler.on_touch_move(identifier, point) {
             TouchAction::Scroll(delta) => {
                 match point.cast() {
-                    Some(point) => self.on_scroll_window_event(ScrollLocation::Delta(
-                                                               webrender_traits::LayerPoint::from_untyped(
-                                                               &delta.to_untyped())),
-                                                               point),
+                    Some(point) => self.on_scroll_window_event(
+                        ScrollLocation::Delta(
+                            LayoutVector2D::from_untyped(&delta.to_untyped())
+                        ),
+                        point
+                    ),
                     None => error!("Point cast failed."),
                 }
             }
             TouchAction::Zoom(magnification, scroll_delta) => {
                 let cursor = TypedPoint2D::new(-1, -1);  // Make sure this hits the base layer.
                 self.pending_scroll_zoom_events.push(ScrollZoomEvent {
                     magnification: magnification,
-                    scroll_location: ScrollLocation::Delta(webrender_traits::LayerPoint::from_untyped(
+                    scroll_location: ScrollLocation::Delta(webrender_traits::LayoutVector2D::from_untyped(
                                                            &scroll_delta.to_untyped())),
                     cursor: cursor,
                     phase: ScrollEventPhase::Move(true),
                     event_count: 1,
                 });
             }
             TouchAction::DispatchEvent => {
                 let dppx = self.page_zoom * self.hidpi_factor();
@@ -1150,33 +1148,33 @@ impl<Window: WindowMethods> IOCompositor
                         ScrollLocation::Delta(delta) => delta,
                         ScrollLocation::Start | ScrollLocation::End => {
                             // If this is an event which is scrolling to the start or end of the page,
                             // disregard other pending events and exit the loop.
                             last_combined_event = Some(scroll_event);
                             break;
                         }
                     };
-                    let delta = (TypedPoint2D::from_untyped(&combined_delta.to_untyped()) / self.scale)
-                                 .to_untyped();
-                    let delta = webrender_traits::LayerPoint::from_untyped(&delta);
+                    // TODO: units don't match!
+                    let delta = combined_delta / self.scale.get();
+
                     let cursor =
                         (combined_event.cursor.to_f32() / self.scale).to_untyped();
                     let location = webrender_traits::ScrollLocation::Delta(delta);
                     let cursor = webrender_traits::WorldPoint::from_untyped(&cursor);
                     self.webrender_api.scroll(location, cursor, combined_event.phase);
                     last_combined_event = None
                 }
             }
 
             match (&mut last_combined_event, scroll_event.phase) {
                 (last_combined_event @ &mut None, _) => {
                     *last_combined_event = Some(ScrollZoomEvent {
                         magnification: scroll_event.magnification,
-                        scroll_location: ScrollLocation::Delta(webrender_traits::LayerPoint::from_untyped(
+                        scroll_location: ScrollLocation::Delta(webrender_traits::LayoutVector2D::from_untyped(
                                                                &this_delta.to_untyped())),
                         cursor: this_cursor,
                         phase: scroll_event.phase,
                         event_count: 1,
                     })
                 }
                 (&mut Some(ref mut last_combined_event),
                  ScrollEventPhase::Move(false)) => {
@@ -1203,19 +1201,19 @@ impl<Window: WindowMethods> IOCompositor
                 }
             }
         }
 
         // TODO(gw): Support zoom (WR issue #28).
         if let Some(combined_event) = last_combined_event {
             let scroll_location = match combined_event.scroll_location {
                 ScrollLocation::Delta(delta) => {
-                    let scaled_delta = (TypedPoint2D::from_untyped(&delta.to_untyped()) / self.scale)
+                    let scaled_delta = (TypedVector2D::from_untyped(&delta.to_untyped()) / self.scale)
                                        .to_untyped();
-                    let calculated_delta = webrender_traits::LayoutPoint::from_untyped(&scaled_delta);
+                    let calculated_delta = webrender_traits::LayoutVector2D::from_untyped(&scaled_delta);
                                            ScrollLocation::Delta(calculated_delta)
                 },
                 // Leave ScrollLocation unchanged if it is Start or End location.
                 sl @ ScrollLocation::Start | sl @ ScrollLocation::End => sl,
             };
             let cursor = (combined_event.cursor.to_f32() / self.scale).to_untyped();
             let cursor = webrender_traits::WorldPoint::from_untyped(&cursor);
             self.webrender_api.scroll(scroll_location, cursor, combined_event.phase);
@@ -1313,17 +1311,17 @@ impl<Window: WindowMethods> IOCompositor
         let page_zoom = webrender_traits::ZoomFactor::new(self.page_zoom.get());
         self.webrender_api.set_page_zoom(page_zoom);
     }
 
     /// Simulate a pinch zoom
     fn on_pinch_zoom_window_event(&mut self, magnification: f32) {
         self.pending_scroll_zoom_events.push(ScrollZoomEvent {
             magnification: magnification,
-            scroll_location: ScrollLocation::Delta(TypedPoint2D::zero()), // TODO: Scroll to keep the center in view?
+            scroll_location: ScrollLocation::Delta(TypedVector2D::zero()), // TODO: Scroll to keep the center in view?
             cursor:  TypedPoint2D::new(-1, -1), // Make sure this hits the base layer.
             phase: ScrollEventPhase::Move(true),
             event_count: 1,
         });
     }
 
     fn on_navigation_window_event(&self, direction: WindowNavigateMsg) {
         let direction = match direction {
--- a/servo/components/compositing/compositor_thread.rs
+++ b/servo/components/compositing/compositor_thread.rs
@@ -1,18 +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/. */
 
 //! Communication with the compositor thread.
 
 use SendableFrameTree;
 use compositor::CompositingReason;
-use euclid::point::Point2D;
-use euclid::size::Size2D;
+use euclid::{Point2D, Size2D};
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState, PipelineId};
 use net_traits::image::base::Image;
 use profile_traits::mem;
 use profile_traits::time;
 use script_traits::{AnimationState, ConstellationMsg, EventResult, LoadData};
 use servo_url::ServoUrl;
 use std::fmt::{Debug, Error, Formatter};
--- a/servo/components/compositing/lib.rs
+++ b/servo/components/compositing/lib.rs
@@ -21,17 +21,17 @@ extern crate servo_geometry;
 extern crate servo_url;
 extern crate style_traits;
 extern crate time;
 extern crate webrender;
 extern crate webrender_traits;
 
 pub use compositor_thread::CompositorProxy;
 pub use compositor::IOCompositor;
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::PipelineId;
 use msg::constellation_msg::TopLevelBrowsingContextId;
 use script_traits::{ConstellationControlMsg, LayoutControlMsg};
 use style_traits::CSSPixel;
 
 mod compositor;
 pub mod compositor_thread;
--- a/servo/components/compositing/touch.rs
+++ b/servo/components/compositing/touch.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 http://mozilla.org/MPL/2.0/. */
 
-use euclid::point::TypedPoint2D;
-use euclid::scale_factor::ScaleFactor;
+use euclid::{TypedPoint2D, TypedVector2D};
+use euclid::ScaleFactor;
 use script_traits::{DevicePixel, EventResult, TouchId};
 use self::TouchState::*;
 
 /// Minimum number of `DeviceIndependentPixel` to begin touch scrolling.
 const TOUCH_PAN_MIN_SCREEN_PX: f32 = 20.0;
 
 pub struct TouchHandler {
     pub state: TouchState,
@@ -51,19 +51,19 @@ pub enum TouchState {
 }
 
 /// The action to take in response to a touch event
 #[derive(Clone, Copy, Debug)]
 pub enum TouchAction {
     /// Simulate a mouse click.
     Click,
     /// Scroll by the provided offset.
-    Scroll(TypedPoint2D<f32, DevicePixel>),
+    Scroll(TypedVector2D<f32, DevicePixel>),
     /// Zoom by a magnification factor and scroll by the provided offset.
-    Zoom(f32, TypedPoint2D<f32, DevicePixel>),
+    Zoom(f32, TypedVector2D<f32, DevicePixel>),
     /// Send a JavaScript event to content.
     DispatchEvent,
     /// Don't do anything.
     NoAction,
 }
 
 impl TouchHandler {
     pub fn new() -> Self {
@@ -216,16 +216,14 @@ impl TouchHandler {
     fn touch_count(&self) -> usize {
         self.active_touch_points.len()
     }
 
     fn pinch_distance_and_center(&self) -> (f32, TypedPoint2D<f32, DevicePixel>) {
         debug_assert!(self.touch_count() == 2);
         let p0 = self.active_touch_points[0].point;
         let p1 = self.active_touch_points[1].point;
-        let center = (p0 + p1) / ScaleFactor::new(2.0);
-
-        let d = p0 - p1;
-        let distance = f32::sqrt(d.x * d.x + d.y * d.y);
+        let center = p0.lerp(p1, 0.5);
+        let distance = (p0 - p1).length();
 
         (distance, center)
     }
 }
--- a/servo/components/compositing/windowing.rs
+++ b/servo/components/compositing/windowing.rs
@@ -1,20 +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/. */
 
 //! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
 
 use compositor_thread::EventLoopWaker;
 use euclid::{Point2D, Size2D};
-use euclid::point::TypedPoint2D;
-use euclid::rect::TypedRect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::TypedSize2D;
+use euclid::{TypedPoint2D, TypedRect, ScaleFactor, TypedSize2D};
 use gleam::gl;
 use msg::constellation_msg::{Key, KeyModifiers, KeyState};
 use net_traits::net_error_list::NetError;
 use script_traits::{DevicePixel, LoadData, MouseButton, TouchEventType, TouchId, TouchpadPressurePhase};
 use servo_geometry::DeviceIndependentPixel;
 use servo_url::ServoUrl;
 use std::fmt::{Debug, Error, Formatter};
 use std::rc::Rc;
--- a/servo/components/config/Cargo.toml
+++ b/servo/components/config/Cargo.toml
@@ -5,17 +5,17 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "servo_config"
 path = "lib.rs"
 
 [dependencies]
-euclid = "0.13"
+euclid = "0.14.4"
 getopts = "0.2.11"
 lazy_static = "0.2"
 log = "0.3.5"
 num_cpus = "1.1.0"
 rustc-serialize = "0.3"
 serde = {version = "0.9"}
 serde_derive = {version = "0.9"}
 servo_geometry = {path = "../geometry"}
--- a/servo/components/config/opts.rs
+++ b/servo/components/config/opts.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/. */
 
 //! Configuration options for a single run of the servo application. Created
 //! from command line arguments.
 
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use getopts::Options;
 use num_cpus;
 use prefs::{self, PrefValue, PREFS};
 use resource_files::set_resources_path;
 use servo_geometry::DeviceIndependentPixel;
 use servo_url::ServoUrl;
 use std::borrow::Cow;
 use std::cmp;
--- a/servo/components/constellation/Cargo.toml
+++ b/servo/components/constellation/Cargo.toml
@@ -13,28 +13,28 @@ path = "lib.rs"
 backtrace = "0.3"
 bluetooth_traits = { path = "../bluetooth_traits" }
 canvas = {path = "../canvas"}
 clipboard = "0.3"
 canvas_traits = {path = "../canvas_traits"}
 compositing = {path = "../compositing"}
 debugger = {path = "../debugger"}
 devtools_traits = {path = "../devtools_traits"}
-euclid = "0.13"
+euclid = "0.14.4"
 gfx = {path = "../gfx"}
 gfx_traits = {path = "../gfx_traits"}
 hyper = "0.10"
 ipc-channel = "0.7"
 itertools = "0.5"
 layout_traits = {path = "../layout_traits"}
 log = "0.3.5"
 msg = {path = "../msg"}
 net = {path = "../net"}
 net_traits = {path = "../net_traits"}
-offscreen_gl_context = "0.8"
+offscreen_gl_context = { version = "0.9", features = ["serde"] }
 profile_traits = {path = "../profile_traits"}
 script_traits = {path = "../script_traits"}
 serde = "0.9"
 serde_derive = "0.9"
 style_traits = {path = "../style_traits"}
 servo_config = {path = "../config"}
 servo_rand = {path = "../rand"}
 servo_remutex = {path = "../remutex"}
--- a/servo/components/constellation/browsingcontext.rs
+++ b/servo/components/constellation/browsingcontext.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::size::TypedSize2D;
+use euclid::TypedSize2D;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, PipelineId};
 use pipeline::Pipeline;
 use script_traits::LoadData;
 use std::collections::HashMap;
 use std::iter::once;
 use std::mem::replace;
 use std::time::Instant;
 use style_traits::CSSPixel;
--- a/servo/components/constellation/constellation.rs
+++ b/servo/components/constellation/constellation.rs
@@ -73,18 +73,17 @@ use canvas::canvas_paint_thread::CanvasP
 use canvas::webgl_paint_thread::WebGLPaintThread;
 use canvas_traits::CanvasMsg;
 use clipboard::{ClipboardContext, ClipboardProvider};
 use compositing::SendableFrameTree;
 use compositing::compositor_thread::CompositorProxy;
 use compositing::compositor_thread::Msg as ToCompositorMsg;
 use debugger;
 use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::{Size2D, TypedSize2D};
+use euclid::{Size2D, TypedSize2D, ScaleFactor};
 use event_loop::EventLoop;
 use gfx::font_cache_thread::FontCacheThread;
 use gfx_traits::Epoch;
 use ipc_channel::{Error as IpcError};
 use ipc_channel::ipc::{self, IpcSender, IpcReceiver};
 use ipc_channel::router::ROUTER;
 use itertools::Itertools;
 use layout_traits::LayoutThreadFactory;
--- a/servo/components/constellation/pipeline.rs
+++ b/servo/components/constellation/pipeline.rs
@@ -2,18 +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 bluetooth_traits::BluetoothRequest;
 use compositing::CompositionPipeline;
 use compositing::CompositorProxy;
 use compositing::compositor_thread::Msg as CompositorMsg;
 use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::TypedSize2D;
+use euclid::{TypedSize2D, ScaleFactor};
 use event_loop::EventLoop;
 use gfx::font_cache_thread::FontCacheThread;
 use ipc_channel::Error;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use ipc_channel::router::ROUTER;
 use layout_traits::LayoutThreadFactory;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, PipelineId, PipelineNamespaceId};
 use net::image_cache::ImageCacheImpl;
--- a/servo/components/geometry/Cargo.toml
+++ b/servo/components/geometry/Cargo.toml
@@ -10,10 +10,10 @@ name = "servo_geometry"
 path = "lib.rs"
 
 [features]
 # servo as opposed to geckolib
 servo = ["euclid/unstable"]
 
 [dependencies]
 app_units = "0.4.1"
-euclid = "0.13"
+euclid = "0.14"
 heapsize = "0.4"
--- a/servo/components/geometry/lib.rs
+++ b/servo/components/geometry/lib.rs
@@ -2,19 +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/. */
 
 extern crate app_units;
 extern crate euclid;
 #[macro_use] extern crate heapsize;
 
 use app_units::{Au, MAX_AU, MIN_AU};
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Point2D, Rect, Size2D};
 
 // Units for use with euclid::length and euclid::scale_factor.
 
 /// A normalized "pixel" at the default resolution for the display.
 ///
 /// Like the CSS "px" unit, the exact physical size of this unit may vary between devices, but it
 /// should approximate a device-independent reference length.  This unit corresponds to Android's
 /// "density-independent pixel" (dip), Mac OS X's "point", and Windows "device-independent pixel."
--- a/servo/components/gfx/Cargo.toml
+++ b/servo/components/gfx/Cargo.toml
@@ -8,17 +8,17 @@ publish = false
 
 [lib]
 name = "gfx"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4.1"
 bitflags = "0.7"
-euclid = "0.13"
+euclid = "0.14.4"
 fnv = "1.0"
 fontsan = {git = "https://github.com/servo/fontsan"}
 gfx_traits = {path = "../gfx_traits"}
 harfbuzz-sys = "0.1"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 ipc-channel = "0.7"
 lazy_static = "0.2"
--- a/servo/components/gfx/display_list/mod.rs
+++ b/servo/components/gfx/display_list/mod.rs
@@ -10,20 +10,18 @@
 //! (although this benefit does not apply to GPU-based painting).
 //!
 //! Display items describe relatively high-level drawing operations (for example, entire borders
 //! and shadows instead of lines and blur operations), to reduce the amount of allocation required.
 //! They are therefore not exactly analogous to constructs like Skia pictures, which consist of
 //! low-level drawing primitives.
 
 use app_units::Au;
-use euclid::{Matrix4D, Point2D, Rect, Size2D};
+use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D, TypedRect, SideOffsets2D};
 use euclid::num::{One, Zero};
-use euclid::rect::TypedRect;
-use euclid::side_offsets::SideOffsets2D;
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use ipc_channel::ipc::IpcSharedMemory;
 use msg::constellation_msg::PipelineId;
 use net_traits::image::base::{Image, PixelFormat};
 use range::Range;
 use servo_geometry::max_rect;
 use std::cmp::{self, Ordering};
@@ -61,60 +59,60 @@ impl<'a> ScrollOffsetLookup<'a> {
             parents: parents,
             calculated_total_offsets: HashMap::new(),
             raw_offsets: raw_offsets,
         }
     }
 
     fn new_for_reference_frame(&mut self,
                                clip_id: ClipId,
-                               transform: &Matrix4D<f32>,
+                               transform: &Transform3D<f32>,
                                point: &mut Point2D<Au>)
                                -> Option<ScrollOffsetLookup> {
         // If a transform function causes the current transformation matrix of an object
         // to be non-invertible, the object and its content do not get displayed.
         let inv_transform = match transform.inverse() {
             Some(transform) => transform,
             None => return None,
         };
 
         let scroll_offset = self.full_offset_for_scroll_root(&clip_id);
         *point = Point2D::new(point.x - Au::from_f32_px(scroll_offset.x),
                               point.y - Au::from_f32_px(scroll_offset.y));
-        let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(),
-                                                                     point.y.to_f32_px()));
+        let frac_point = inv_transform.transform_point2d(&Point2D::new(point.x.to_f32_px(),
+                                                                       point.y.to_f32_px()));
         *point = Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y));
 
         let mut sublookup = ScrollOffsetLookup {
             parents: &mut self.parents,
             calculated_total_offsets: HashMap::new(),
             raw_offsets: self.raw_offsets,
         };
-        sublookup.calculated_total_offsets.insert(clip_id, Point2D::zero());
+        sublookup.calculated_total_offsets.insert(clip_id, Vector2D::zero());
         Some(sublookup)
     }
 
     fn add_scroll_root(&mut self, scroll_root: &ScrollRoot) {
         self.parents.insert(scroll_root.id, scroll_root.parent_id);
     }
 
-    fn full_offset_for_scroll_root(&mut self, id: &ClipId) -> Point2D<f32> {
+    fn full_offset_for_scroll_root(&mut self, id: &ClipId) -> Vector2D<f32> {
         if let Some(offset) = self.calculated_total_offsets.get(id) {
             return *offset;
         }
 
         let parent_offset = if !id.is_root_scroll_node() {
             let parent_id = *self.parents.get(id).unwrap();
             self.full_offset_for_scroll_root(&parent_id)
         } else {
-            Point2D::zero()
+            Vector2D::zero()
         };
 
         let offset = parent_offset +
-                     self.raw_offsets.get(id).cloned().unwrap_or_else(Point2D::zero);
+                     self.raw_offsets.get(id).cloned().unwrap_or_else(Vector2D::zero);
         self.calculated_total_offsets.insert(*id, offset);
         offset
     }
 }
 
 impl DisplayList {
     /// Return the bounds of this display list based on the dimensions of the root
     /// stacking context.
@@ -179,20 +177,20 @@ impl DisplayList {
     fn text_index_stacking_context<'a>(&self,
                                        stacking_context: &StackingContext,
                                        clip_id: ClipId,
                                        node: OpaqueNode,
                                        traversal: &mut DisplayListTraversal<'a>,
                                        point: &Point2D<Au>,
                                        offset_lookup: &mut ScrollOffsetLookup,
                                        result: &mut Vec<usize>) {
-        let mut point = *point - stacking_context.bounds.origin;
+        let mut point = *point - stacking_context.bounds.origin.to_vector();
         if stacking_context.scroll_policy == ScrollPolicy::Fixed {
             let old_offset = offset_lookup.calculated_total_offsets.get(&clip_id).cloned();
-            offset_lookup.calculated_total_offsets.insert(clip_id, Point2D::zero());
+            offset_lookup.calculated_total_offsets.insert(clip_id, Vector2D::zero());
 
             self.text_index_contents(node, traversal, &point, offset_lookup, result);
 
             match old_offset {
                 Some(offset) => offset_lookup.calculated_total_offsets.insert(clip_id, offset),
                 None => offset_lookup.calculated_total_offsets.remove(&clip_id),
             };
         } else if let Some(transform) = stacking_context.transform {
@@ -252,20 +250,20 @@ impl DisplayList {
                                      stacking_context: &StackingContext,
                                      clip_id: ClipId,
                                      traversal: &mut DisplayListTraversal<'a>,
                                      point: &Point2D<Au>,
                                      offset_lookup: &mut ScrollOffsetLookup,
                                      result: &mut Vec<DisplayItemMetadata>) {
         debug_assert!(stacking_context.context_type == StackingContextType::Real);
 
-        let mut point = *point - stacking_context.bounds.origin;
+        let mut point = *point - stacking_context.bounds.origin.to_vector();
         if stacking_context.scroll_policy == ScrollPolicy::Fixed {
             let old_offset = offset_lookup.calculated_total_offsets.get(&clip_id).cloned();
-            offset_lookup.calculated_total_offsets.insert(clip_id, Point2D::zero());
+            offset_lookup.calculated_total_offsets.insert(clip_id, Vector2D::zero());
 
             self.hit_test_contents(traversal, &point, offset_lookup, result);
 
             match old_offset {
                 Some(offset) => offset_lookup.calculated_total_offsets.insert(clip_id, offset),
                 None => offset_lookup.calculated_total_offsets.remove(&clip_id),
             };
         } else if let Some(transform) = stacking_context.transform {
@@ -422,23 +420,23 @@ pub struct StackingContext {
 
     /// CSS filters to be applied to this stacking context (including opacity).
     pub filters: filter::T,
 
     /// The blend mode with which this stacking context blends with its backdrop.
     pub mix_blend_mode: MixBlendMode,
 
     /// A transform to be applied to this stacking context.
-    pub transform: Option<Matrix4D<f32>>,
+    pub transform: Option<Transform3D<f32>>,
 
     /// The transform style of this stacking context.
     pub transform_style: TransformStyle,
 
     /// The perspective matrix to be applied to children.
-    pub perspective: Option<Matrix4D<f32>>,
+    pub perspective: Option<Transform3D<f32>>,
 
     /// The scroll policy of this layer.
     pub scroll_policy: ScrollPolicy,
 
     /// The id of the parent scrolling area that contains this StackingContext.
     pub parent_scroll_id: ClipId,
 }
 
@@ -447,19 +445,19 @@ impl StackingContext {
     #[inline]
     pub fn new(id: StackingContextId,
                context_type: StackingContextType,
                bounds: &Rect<Au>,
                overflow: &Rect<Au>,
                z_index: i32,
                filters: filter::T,
                mix_blend_mode: MixBlendMode,
-               transform: Option<Matrix4D<f32>>,
+               transform: Option<Transform3D<f32>>,
                transform_style: TransformStyle,
-               perspective: Option<Matrix4D<f32>>,
+               perspective: Option<Transform3D<f32>>,
                scroll_policy: ScrollPolicy,
                parent_scroll_id: ClipId)
                -> StackingContext {
         StackingContext {
             id: id,
             context_type: context_type,
             bounds: *bounds,
             overflow: *overflow,
@@ -797,17 +795,17 @@ impl ClippingRegion {
         self.complex.push(ComplexClippingRegion {
             rect: *rect,
             radii: *radii,
         });
     }
 
     /// Translates this clipping region by the given vector.
     #[inline]
-    pub fn translate(&self, delta: &Point2D<Au>) -> ClippingRegion {
+    pub fn translate(&self, delta: &Vector2D<Au>) -> ClippingRegion {
         ClippingRegion {
             main: self.main.translate(delta),
             complex: self.complex.iter().map(|complex| {
                 ComplexClippingRegion {
                     rect: complex.rect.translate(delta),
                     radii: complex.radii,
                 }
             }).collect(),
@@ -1153,17 +1151,17 @@ pub struct LineDisplayItem {
 pub struct BoxShadowDisplayItem {
     /// Fields common to all display items.
     pub base: BaseDisplayItem,
 
     /// The dimensions of the box that we're placing a shadow around.
     pub box_bounds: Rect<Au>,
 
     /// The offset of this shadow from the box.
-    pub offset: Point2D<Au>,
+    pub offset: Vector2D<Au>,
 
     /// The color of this shadow.
     pub color: ColorF,
 
     /// The blur radius for this shadow.
     pub blur_radius: Au,
 
     /// The spread radius of this shadow.
@@ -1378,24 +1376,24 @@ impl WebRenderImageInfo {
             height: image.height,
             format: image.format,
             key: image.id,
         }
     }
 }
 
 /// The type of the scroll offset list. This is only populated if WebRender is in use.
-pub type ScrollOffsetMap = HashMap<ClipId, Point2D<f32>>;
+pub type ScrollOffsetMap = HashMap<ClipId, Vector2D<f32>>;
 
 
 pub trait SimpleMatrixDetection {
     fn is_identity_or_simple_translation(&self) -> bool;
 }
 
-impl SimpleMatrixDetection for Matrix4D<f32> {
+impl SimpleMatrixDetection for Transform3D<f32> {
     #[inline]
     fn is_identity_or_simple_translation(&self) -> bool {
         let (_0, _1) = (Zero::zero(), One::one());
         self.m11 == _1 && self.m12 == _0 && self.m13 == _0 && self.m14 == _0 &&
         self.m21 == _0 && self.m22 == _1 && self.m23 == _0 && self.m24 == _0 &&
         self.m31 == _0 && self.m32 == _0 && self.m33 == _1 && self.m34 == _0 &&
         self.m44 == _1
     }
--- a/servo/components/gfx/text/glyph.rs
+++ b/servo/components/gfx/text/glyph.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 http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use euclid::point::Point2D;
+use euclid::Point2D;
 use range::{self, EachIndex, Range, RangeIndex};
 #[cfg(any(target_feature = "sse2", target_feature = "neon"))]
 use simd::u32x4;
 use std::{fmt, mem, u16};
 use std::cmp::{Ordering, PartialOrd};
 use std::vec::Vec;
 
 pub use gfx_traits::ByteIndex;
--- a/servo/components/layout/Cargo.toml
+++ b/servo/components/layout/Cargo.toml
@@ -9,17 +9,17 @@ publish = false
 name = "layout"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4.1"
 atomic_refcell = "0.1"
 bitflags = "0.7"
 canvas_traits = {path = "../canvas_traits"}
-euclid = "0.13"
+euclid = "0.14.4"
 fnv = "1.0"
 gfx = {path = "../gfx"}
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.4"
 html5ever = "0.17"
 ipc-channel = "0.7"
 libc = "0.2"
 log = "0.3.5"
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -1962,17 +1962,17 @@ impl Flow for BlockFlow {
             let absolute_stacking_relative_position = if self.is_fixed() {
                 // The viewport is initially at (0, 0).
                 position_start
             } else {
                 // Absolute position of the containing block + position of absolute
                 // flow w.r.t. the containing block.
                 self.base
                     .late_absolute_position_info
-                    .stacking_relative_position_of_absolute_containing_block + position_start
+                    .stacking_relative_position_of_absolute_containing_block + position_start.to_vector()
             };
 
             if !self.base.writing_mode.is_vertical() {
                 if !self.base.flags.contains(INLINE_POSITION_IS_STATIC) {
                     self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
                 }
                 if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
                     self.base.stacking_relative_position.y = absolute_stacking_relative_position.y
@@ -1995,19 +1995,19 @@ impl Flow for BlockFlow {
                                                  .early_absolute_position_info
                                                  .relative_containing_block_size);
         if self.contains_positioned_fragments() {
             let border_box_origin = (self.fragment.border_box -
                 self.fragment.style.logical_border_width()).start;
             self.base
                 .late_absolute_position_info
                 .stacking_relative_position_of_absolute_containing_block =
-                    self.base.stacking_relative_position +
+                    self.base.stacking_relative_position.to_point() +
                      (border_box_origin + relative_offset).to_physical(self.base.writing_mode,
-                                                                       container_size)
+                                                                       container_size).to_vector()
         }
 
         // Compute absolute position info for children.
         let stacking_relative_position_of_absolute_containing_block_for_children =
             if self.fragment.establishes_stacking_context() {
                 let logical_border_width = self.fragment.style().logical_border_width();
                 let position = LogicalPoint::new(self.base.writing_mode,
                                                  logical_border_width.inline_start,
@@ -2031,29 +2031,29 @@ impl Flow for BlockFlow {
         let late_absolute_position_info_for_children = LateAbsolutePositionInfo {
             stacking_relative_position_of_absolute_containing_block:
                 stacking_relative_position_of_absolute_containing_block_for_children,
         };
         let container_size_for_children =
             self.base.position.size.to_physical(self.base.writing_mode);
 
         // Compute the origin and clipping rectangle for children.
-        let relative_offset = relative_offset.to_physical(self.base.writing_mode);
+        let relative_offset = relative_offset.to_physical(self.base.writing_mode).to_vector();
         let is_stacking_context = self.fragment.establishes_stacking_context();
         let origin_for_children = if is_stacking_context {
             // We establish a stacking context, so the position of our children is vertically
             // correct, but has to be adjusted to accommodate horizontal margins. (Note the
             // calculation involving `position` below and recall that inline-direction flow
             // positions are relative to the edges of the margin box.)
             //
             // FIXME(pcwalton): Is this vertical-writing-direction-safe?
             let margin = self.fragment.margin.to_physical(self.base.writing_mode);
             Point2D::new(-margin.left, Au(0))
         } else {
-            self.base.stacking_relative_position + relative_offset
+            self.base.stacking_relative_position.to_point() + relative_offset
         };
 
         // Process children.
         for kid in self.base.child_iter_mut() {
             if flow::base(kid).flags.contains(INLINE_POSITION_IS_STATIC) ||
                     flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
                 let kid_base = flow::mut_base(kid);
                 let physical_position = kid_base.position.to_physical(kid_base.writing_mode,
@@ -2166,17 +2166,17 @@ impl Flow for BlockFlow {
                               .stacking_relative_border_box(&self.base.stacking_relative_position,
                                                             &self.base
                                                                  .early_absolute_position_info
                                                                  .relative_containing_block_size,
                                                             self.base
                                                                 .early_absolute_position_info
                                                                 .relative_containing_block_mode,
                                                             CoordinateSystem::Own)
-                              .translate(stacking_context_position));
+                              .translate(&stacking_context_position.to_vector()));
     }
 
     fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) {
         (*mutator)(&mut self.fragment)
     }
 
     fn print_extra_flow_children(&self, print_tree: &mut PrintTree) {
         print_tree.add_item(format!("↑↑ Fragment for block: {:?}", self.fragment));
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -9,17 +9,17 @@
 //! paint.
 
 #![deny(unsafe_code)]
 
 use app_units::{AU_PER_PX, Au};
 use block::{BlockFlow, BlockStackingContextType};
 use canvas_traits::{CanvasData, CanvasMsg, FromLayoutMsg};
 use context::LayoutContext;
-use euclid::{Matrix4D, Point2D, Rect, SideOffsets2D, Size2D, TypedSize2D};
+use euclid::{Transform3D, Point2D, Vector2D, Rect, SideOffsets2D, Size2D, TypedSize2D};
 use flex::FlexFlow;
 use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
 use flow_ref::FlowRef;
 use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
 use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
 use gfx::display_list;
 use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails};
 use gfx::display_list::{BorderDisplayItem, ImageBorder, NormalBorder};
@@ -496,17 +496,17 @@ pub trait FragmentDisplayListBuilding {
     /// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
     /// * `stacking_relative_flow_origin`: Position of the origin of the owning flow with respect
     ///   to its nearest ancestor stacking context.
     /// * `relative_containing_block_size`: The size of the containing block that
     ///   `position: relative` makes use of.
     /// * `clip`: The region to clip the display items to.
     fn build_display_list(&mut self,
                           state: &mut DisplayListBuildState,
-                          stacking_relative_flow_origin: &Point2D<Au>,
+                          stacking_relative_flow_origin: &Vector2D<Au>,
                           relative_containing_block_size: &LogicalSize<Au>,
                           relative_containing_block_mode: WritingMode,
                           border_painting_mode: BorderPaintingMode,
                           display_list_section: DisplayListSection,
                           clip: &Rect<Au>);
 
     /// Builds the display items necessary to paint the selection and/or caret for this fragment,
     /// if any.
@@ -1218,18 +1218,18 @@ impl FragmentDisplayListBuilding for Fra
 
         let line_length = (dir.x * bounds.size.width.to_f32_px()).abs() +
                           (dir.y * bounds.size.height.to_f32_px()).abs();
 
         let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
 
         // This is the vector between the center and the ending point; i.e. half
         // of the distance between the starting point and the ending point.
-        let delta = Point2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
-                                 Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
+        let delta = Vector2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
+                                  Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
 
         // This is the length of the gradient line.
         let length = Au::from_f32_px(
             (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
 
         let mut stops = convert_gradient_stops(stops, length);
 
         // Only clamped gradients need to be fixed because in repeating gradients
@@ -1342,32 +1342,32 @@ impl FragmentDisplayListBuilding for Fra
                                                        state: &mut DisplayListBuildState,
                                                        style: &ServoComputedValues,
                                                        display_list_section: DisplayListSection,
                                                        absolute_bounds: &Rect<Au>,
                                                        clip: &Rect<Au>) {
         // NB: According to CSS-BACKGROUNDS, box shadows render in *reverse* order (front to back).
         for box_shadow in style.get_effects().box_shadow.0.iter().rev() {
             let bounds =
-                shadow_bounds(&absolute_bounds.translate(&Point2D::new(box_shadow.offset_x,
-                                                                       box_shadow.offset_y)),
+                shadow_bounds(&absolute_bounds.translate(&Vector2D::new(box_shadow.offset_x,
+                                                                        box_shadow.offset_y)),
                               box_shadow.blur_radius,
                               box_shadow.spread_radius);
 
             // TODO(pcwalton): Multiple border radii; elliptical border radii.
             let base = state.create_base_display_item(&bounds,
                                                       &ClippingRegion::from_rect(&clip),
                                                       self.node,
                                                       style.get_cursor(Cursor::Default),
                                                       display_list_section);
             state.add_display_item(DisplayItem::BoxShadow(box BoxShadowDisplayItem {
                 base: base,
                 box_bounds: *absolute_bounds,
                 color: style.resolve_color(box_shadow.color).to_gfx_color(),
-                offset: Point2D::new(box_shadow.offset_x, box_shadow.offset_y),
+                offset: Vector2D::new(box_shadow.offset_x, box_shadow.offset_y),
                 blur_radius: box_shadow.blur_radius,
                 spread_radius: box_shadow.spread_radius,
                 border_radius: model::specified_border_radius(style.get_border()
                                                                    .border_top_left_radius,
                                                               absolute_bounds.size).width,
                 clip_mode: if box_shadow.inset {
                     BoxShadowClipMode::Inset
                 } else {
@@ -1702,17 +1702,17 @@ impl FragmentDisplayListBuilding for Fra
         state.add_display_item(DisplayItem::SolidColor(box SolidColorDisplayItem {
             base: base,
             color: self.style().get_color().color.to_gfx_color(),
         }));
     }
 
     fn build_display_list(&mut self,
                           state: &mut DisplayListBuildState,
-                          stacking_relative_flow_origin: &Point2D<Au>,
+                          stacking_relative_flow_origin: &Vector2D<Au>,
                           relative_containing_block_size: &LogicalSize<Au>,
                           relative_containing_block_mode: WritingMode,
                           border_painting_mode: BorderPaintingMode,
                           display_list_section: DisplayListSection,
                           clip: &Rect<Au>) {
         self.restyle_damage.remove(REPAINT);
         if self.style().get_inheritedbox().visibility != visibility::T::visible {
             return
@@ -1996,17 +1996,17 @@ impl FragmentDisplayListBuilding for Fra
                                                base_flow.early_absolute_position_info
                                                           .relative_containing_block_mode,
                                                CoordinateSystem::Parent);
         // First, compute the offset of our border box (including relative positioning)
         // from our flow origin, since that is what `BaseFlow::overflow` is relative to.
         let border_box_offset =
             border_box.translate(&-base_flow.stacking_relative_position).origin;
         // Then, using that, compute our overflow region relative to our border box.
-        let overflow = base_flow.overflow.paint.translate(&-border_box_offset);
+        let overflow = base_flow.overflow.paint.translate(&-border_box_offset.to_vector());
 
         // Create the filter pipeline.
         let effects = self.style().get_effects();
         let mut filters = effects.filter.clone();
         if effects.opacity != 1.0 {
             filters.push(Filter::Opacity(effects.opacity))
         }
 
@@ -2041,17 +2041,17 @@ impl FragmentDisplayListBuilding for Fra
             // If we're painting a shadow, paint the text the same color as the shadow.
             self.style().resolve_color(shadow.color)
         } else if text_fragment.selected() {
             // Otherwise, paint the text with the color as described in its styling.
             self.selected_style().get_color().color
         } else {
             self.style().get_color().color
         };
-        let offset = text_shadow.map(|s| Point2D::new(s.offset_x, s.offset_y)).unwrap_or_else(Point2D::zero);
+        let offset = text_shadow.map(|s| Vector2D::new(s.offset_x, s.offset_y)).unwrap_or_else(Vector2D::zero);
         let shadow_blur_radius = text_shadow.map(|s| s.blur_radius).unwrap_or(Au(0));
 
         // Determine the orientation and cursor to use.
         let (orientation, cursor) = if self.style.writing_mode.is_vertical() {
             // TODO: Distinguish between 'sideways-lr' and 'sideways-rl' writing modes in CSS
             // Writing Modes Level 4.
             (TextOrientation::SidewaysRight, Cursor::VerticalText)
         } else {
@@ -2063,17 +2063,17 @@ impl FragmentDisplayListBuilding for Fra
         // FIXME(pcwalton): Get the real container size.
         let container_size = Size2D::zero();
         let metrics = &text_fragment.run.font_metrics;
         let stacking_relative_content_box = stacking_relative_content_box.translate(&offset);
         let baseline_origin = stacking_relative_content_box.origin +
             LogicalPoint::new(self.style.writing_mode,
                               Au(0),
                               metrics.ascent).to_physical(self.style.writing_mode,
-                                                          container_size);
+                                                          container_size).to_vector();
 
         // Create the text display item.
         let base = state.create_base_display_item(&stacking_relative_content_box,
                                                   &ClippingRegion::from_rect(&clip),
                                                   self.node,
                                                   self.style().get_cursor(cursor),
                                                   DisplayListSection::Content);
         state.add_display_item(DisplayItem::Text(box TextDisplayItem {
@@ -2153,17 +2153,17 @@ impl FragmentDisplayListBuilding for Fra
             &ClippingRegion::from_rect(&clip),
             self.node,
             self.style.get_cursor(Cursor::Default),
             DisplayListSection::Content);
         state.add_display_item(DisplayItem::BoxShadow(box BoxShadowDisplayItem {
             base: base,
             box_bounds: stacking_relative_box,
             color: color.to_gfx_color(),
-            offset: Point2D::zero(),
+            offset: Vector2D::zero(),
             blur_radius: blur_radius,
             spread_radius: Au(0),
             border_radius: Au(0),
             clip_mode: BoxShadowClipMode::None,
         }));
     }
 
     fn unique_id(&self, id_type: IdType) -> u64 {
@@ -2295,17 +2295,17 @@ impl BlockFlowDisplayListBuilding for Bl
         }
         let border_box = self.stacking_relative_position(CoordinateSystem::Parent);
         let transform = match self.fragment.transform_matrix(&border_box) {
             Some(transform) => transform,
             None => return,
         };
 
         let perspective = self.fragment.perspective_matrix(&border_box)
-                                       .unwrap_or_else(Matrix4D::identity);
+                                       .unwrap_or_else(Transform3D::identity);
         let transform = transform.pre_mul(&perspective).inverse();
 
         let origin = &border_box.origin;
         let transform_clip = |clip: &Rect<Au>| {
             if *clip == max_rect() {
                 return *clip;
             }
 
@@ -2813,17 +2813,17 @@ impl BaseFlowDisplayListBuilding for Bas
                                               state: &mut DisplayListBuildState,
                                               node: OpaqueNode) {
         if !opts::get().show_debug_parallel_layout {
             return
         }
 
         let thread_id = self.thread_id;
         let stacking_context_relative_bounds =
-            Rect::new(self.stacking_relative_position,
+            Rect::new(self.stacking_relative_position.to_point(),
                       self.position.size.to_physical(self.writing_mode));
 
         let mut color = THREAD_TINT_COLORS[thread_id as usize % THREAD_TINT_COLORS.len()];
         color.a = 1.0;
         let base = state.create_base_display_item(
             &stacking_context_relative_bounds.inflate(Au::from_px(2), Au::from_px(2)),
             &ClippingRegion::from_rect(&self.clip),
             node,
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -24,17 +24,17 @@
 //!   fragments/flows that are subject to inline layout and line breaking and structs to represent
 //!   line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
 //!   similar methods.
 
 use app_units::Au;
 use block::{BlockFlow, FormattingContextType};
 use context::LayoutContext;
 use display_list_builder::DisplayListBuildState;
-use euclid::{Matrix4D, Point2D, Rect, Size2D};
+use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D};
 use flex::FlexFlow;
 use floats::{Floats, SpeculatedFloatPlacement};
 use flow_list::{FlowList, MutFlowListIterator};
 use flow_ref::{FlowRef, WeakFlowRef};
 use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use inline::InlineFlow;
@@ -255,17 +255,17 @@ pub trait Flow: fmt::Debug + Sync + Send
         let container_size = Size2D::zero();
         let position = base(self).position.to_physical(base(self).writing_mode, container_size);
 
         let mut overflow = base(self).overflow;
 
         match self.class() {
             FlowClass::Block | FlowClass::TableCaption | FlowClass::TableCell => {}
             _ => {
-                overflow.translate(&position.origin);
+                overflow.translate(&position.origin.to_vector());
                 return overflow;
             }
         }
 
         let border_box = self.as_block().fragment.stacking_relative_border_box(
             &base(self).stacking_relative_position,
             &base(self).early_absolute_position_info.relative_containing_block_size,
             base(self).early_absolute_position_info.relative_containing_block_mode,
@@ -280,40 +280,40 @@ pub trait Flow: fmt::Debug + Sync + Send
             overflow.paint.origin.y = Au(0);
             overflow.paint.size.height = border_box.size.height;
             overflow.scroll.origin.y = Au(0);
             overflow.scroll.size.height = border_box.size.height;
         }
 
         if !self.as_block().fragment.establishes_stacking_context() ||
            self.as_block().fragment.style.get_box().transform.0.is_none() {
-            overflow.translate(&position.origin);
+            overflow.translate(&position.origin.to_vector());
             return overflow;
         }
 
         // TODO: Take into account 3d transforms, even though it's a fairly
         // uncommon case.
         let transform_2d = self.as_block()
                                .fragment
                                .transform_matrix(&position)
-                               .unwrap_or(Matrix4D::identity())
+                               .unwrap_or(Transform3D::identity())
                                .to_2d();
         let transformed_overflow = Overflow {
             paint: f32_rect_to_au_rect(transform_2d.transform_rect(
                                        &au_rect_to_f32_rect(overflow.paint))),
             scroll: f32_rect_to_au_rect(transform_2d.transform_rect(
                                        &au_rect_to_f32_rect(overflow.scroll))),
         };
 
         // TODO: We are taking the union of the overflow and transformed overflow here, which
         // happened implicitly in the previous version of this code. This will probably be
         // unnecessary once we are taking into account 3D transformations above.
         overflow.union(&transformed_overflow);
 
-        overflow.translate(&position.origin);
+        overflow.translate(&position.origin.to_vector());
         overflow
     }
 
     ///
     /// CSS Section 11.1
     /// This is the union of rectangles of the flows for which we define the
     /// Containing Block.
     ///
@@ -912,17 +912,17 @@ pub struct BaseFlow {
     /// Metrics for floats out computed during the float metrics speculation phase.
     pub speculated_float_placement_out: SpeculatedFloatPlacement,
 
     /// The collapsible margins for this flow, if any.
     pub collapsible_margins: CollapsibleMargins,
 
     /// The position of this flow relative to the start of the nearest ancestor stacking context.
     /// This is computed during the top-down pass of display list construction.
-    pub stacking_relative_position: Point2D<Au>,
+    pub stacking_relative_position: Vector2D<Au>,
 
     /// Details about descendants with position 'absolute' or 'fixed' for which we are the
     /// containing block. This is in tree order. This includes any direct children.
     pub abs_descendants: AbsoluteDescendants,
 
     /// The inline-size of the block container of this flow. Used for computing percentage and
     /// automatic values for `width`.
     pub block_container_inline_size: Au,
@@ -1093,17 +1093,17 @@ impl BaseFlow {
             restyle_damage: damage,
             children: FlowList::new(),
             intrinsic_inline_sizes: IntrinsicISizes::new(),
             position: LogicalRect::zero(writing_mode),
             overflow: Overflow::new(),
             parallel: FlowParallelInfo::new(),
             floats: Floats::new(writing_mode),
             collapsible_margins: CollapsibleMargins::new(),
-            stacking_relative_position: Point2D::zero(),
+            stacking_relative_position: Vector2D::zero(),
             abs_descendants: AbsoluteDescendants::new(),
             speculated_float_placement_in: SpeculatedFloatPlacement::zero(),
             speculated_float_placement_out: SpeculatedFloatPlacement::zero(),
             block_container_inline_size: Au(0),
             block_container_writing_mode: writing_mode,
             block_container_explicit_block_size: None,
             absolute_cb: ContainingBlockLink::new(),
             early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -5,17 +5,17 @@
 //! The `Fragment` type, which represents the leaves of the layout tree.
 
 #![deny(unsafe_code)]
 
 use StyleArc;
 use app_units::Au;
 use canvas_traits::CanvasMsg;
 use context::{LayoutContext, with_thread_local_font_context};
-use euclid::{Matrix4D, Point2D, Radians, Rect, Size2D};
+use euclid::{Transform3D, Point2D, Vector2D, Radians, Rect, Size2D};
 use floats::ClearType;
 use flow::{self, ImmutableFlowUtils};
 use flow_ref::FlowRef;
 use gfx;
 use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
 use gfx::text::glyph::ByteIndex;
 use gfx::text::text_run::{TextRun, TextRunSlice};
 use gfx_traits::StackingContextId;
@@ -2417,17 +2417,17 @@ impl Fragment {
     /// context's coordinate system. Otherwise, if `coordinate_system` is `Own` and this fragment
     /// establishes a stacking context itself, this returns a border box anchored at (0, 0). (If
     /// this fragment does not establish a stacking context, then it always belongs to its parent
     /// stacking context and thus `coordinate_system` is ignored.)
     ///
     /// This is the method you should use for display list construction as well as
     /// `getBoundingClientRect()` and so forth.
     pub fn stacking_relative_border_box(&self,
-                                        stacking_relative_flow_origin: &Point2D<Au>,
+                                        stacking_relative_flow_origin: &Vector2D<Au>,
                                         relative_containing_block_size: &LogicalSize<Au>,
                                         relative_containing_block_mode: WritingMode,
                                         coordinate_system: CoordinateSystem)
                                         -> Rect<Au> {
         let container_size =
             relative_containing_block_size.to_physical(relative_containing_block_mode);
         let border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
         if coordinate_system == CoordinateSystem::Own && self.establishes_stacking_context() {
@@ -2435,17 +2435,17 @@ impl Fragment {
         }
 
         // FIXME(pcwalton): This can double-count relative position sometimes for inlines (e.g.
         // `<div style="position:relative">x</div>`, because the `position:relative` trickles down
         // to the inline flow. Possibly we should extend the notion of "primary fragment" to fix
         // this.
         let relative_position = self.relative_position(relative_containing_block_size);
         border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode))
-                  .translate(stacking_relative_flow_origin)
+                  .translate(&stacking_relative_flow_origin)
     }
 
     /// Given the stacking-context-relative border box, returns the stacking-context-relative
     /// content box.
     pub fn stacking_relative_content_box(&self, stacking_relative_border_box: &Rect<Au>)
                                          -> Rect<Au> {
         let border_padding = self.border_padding.to_physical(self.style.writing_mode);
         Rect::new(Point2D::new(stacking_relative_border_box.origin.x + border_padding.left,
@@ -2546,17 +2546,17 @@ impl Fragment {
         // the time. Can't we handle relative positioning by just adjusting `border_box`?
         let relative_position = self.relative_position(relative_containing_block_size);
         border_box =
             border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode));
         let mut overflow = Overflow::from_rect(&border_box);
 
         // Box shadows cause us to draw outside our border box.
         for box_shadow in &self.style().get_effects().box_shadow.0 {
-            let offset = Point2D::new(box_shadow.offset_x, box_shadow.offset_y);
+            let offset = Vector2D::new(box_shadow.offset_x, box_shadow.offset_y);
             let inflation = box_shadow.spread_radius + box_shadow.blur_radius *
                 BLUR_INFLATION_FACTOR;
             overflow.paint = overflow.paint.union(&border_box.translate(&offset)
                                                              .inflate(inflation, inflation))
         }
 
         // Outlines cause us to draw outside our border box.
         let outline_width = self.style.get_outline().outline_width;
@@ -2837,104 +2837,104 @@ impl Fragment {
             SpecificFragmentInfo::ScannedText(_) |
             SpecificFragmentInfo::TruncatedFragment(_) |
             SpecificFragmentInfo::Svg(_) |
             SpecificFragmentInfo::UnscannedText(_) => true
         }
     }
 
     /// Returns the 4D matrix representing this fragment's transform.
-    pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Matrix4D<f32>> {
+    pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Transform3D<f32>> {
         let operations = match self.style.get_box().transform.0 {
             None => return None,
             Some(ref operations) => operations,
         };
 
-        let mut transform = Matrix4D::identity();
+        let mut transform = Transform3D::identity();
         let transform_origin = &self.style.get_box().transform_origin;
         let transform_origin_x =
             transform_origin.horizontal
                 .to_used_value(stacking_relative_border_box.size.width)
                 .to_f32_px();
         let transform_origin_y =
             transform_origin.vertical
                 .to_used_value(stacking_relative_border_box.size.height)
                 .to_f32_px();
         let transform_origin_z = transform_origin.depth.to_f32_px();
 
-        let pre_transform = Matrix4D::create_translation(transform_origin_x,
-                                                         transform_origin_y,
-                                                         transform_origin_z);
-        let post_transform = Matrix4D::create_translation(-transform_origin_x,
-                                                          -transform_origin_y,
-                                                          -transform_origin_z);
+        let pre_transform = Transform3D::create_translation(transform_origin_x,
+                                                            transform_origin_y,
+                                                            transform_origin_z);
+        let post_transform = Transform3D::create_translation(-transform_origin_x,
+                                                             -transform_origin_y,
+                                                             -transform_origin_z);
 
         for operation in operations {
             let matrix = match *operation {
                 transform::ComputedOperation::Rotate(ax, ay, az, theta) => {
                     let theta = 2.0f32 * f32::consts::PI - theta.radians();
-                    Matrix4D::create_rotation(ax, ay, az, Radians::new(theta))
+                    Transform3D::create_rotation(ax, ay, az, Radians::new(theta))
                 }
                 transform::ComputedOperation::Perspective(d) => {
                     create_perspective_matrix(d)
                 }
                 transform::ComputedOperation::Scale(sx, sy, sz) => {
-                    Matrix4D::create_scale(sx, sy, sz)
+                    Transform3D::create_scale(sx, sy, sz)
                 }
                 transform::ComputedOperation::Translate(tx, ty, tz) => {
                     let tx = tx.to_used_value(stacking_relative_border_box.size.width).to_f32_px();
                     let ty = ty.to_used_value(stacking_relative_border_box.size.height).to_f32_px();
                     let tz = tz.to_f32_px();
-                    Matrix4D::create_translation(tx, ty, tz)
+                    Transform3D::create_translation(tx, ty, tz)
                 }
                 transform::ComputedOperation::Matrix(m) => {
                     m.to_gfx_matrix()
                 }
                 transform::ComputedOperation::MatrixWithPercents(_) => {
                     // `-moz-transform` is not implemented in Servo yet.
                     unreachable!()
                 }
                 transform::ComputedOperation::Skew(theta_x, theta_y) => {
-                    Matrix4D::create_skew(Radians::new(theta_x.radians()),
+                    Transform3D::create_skew(Radians::new(theta_x.radians()),
                                           Radians::new(theta_y.radians()))
                 }
                 transform::ComputedOperation::InterpolateMatrix { .. } |
                 transform::ComputedOperation::AccumulateMatrix { .. } => {
-                    // TODO: Convert InterpolateMatrix/AccmulateMatrix into a valid Matrix4D by
+                    // TODO: Convert InterpolateMatrix/AccmulateMatrix into a valid Transform3D by
                     // the reference box.
-                    Matrix4D::identity()
+                    Transform3D::identity()
                 }
             };
 
             transform = transform.pre_mul(&matrix);
         }
 
         Some(pre_transform.pre_mul(&transform).pre_mul(&post_transform))
     }
 
     /// Returns the 4D matrix representing this fragment's perspective.
-    pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Matrix4D<f32>> {
+    pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Transform3D<f32>> {
         match self.style().get_box().perspective {
             Either::First(length) => {
                 let perspective_origin = self.style().get_box().perspective_origin;
                 let perspective_origin =
                     Point2D::new(
                         perspective_origin.horizontal
                             .to_used_value(stacking_relative_border_box.size.width)
                             .to_f32_px(),
                         perspective_origin.vertical
                             .to_used_value(stacking_relative_border_box.size.height)
                             .to_f32_px());
 
-                let pre_transform = Matrix4D::create_translation(perspective_origin.x,
-                                                                 perspective_origin.y,
-                                                                 0.0);
-                let post_transform = Matrix4D::create_translation(-perspective_origin.x,
-                                                                  -perspective_origin.y,
-                                                                  0.0);
+                let pre_transform = Transform3D::create_translation(perspective_origin.x,
+                                                                    perspective_origin.y,
+                                                                    0.0);
+                let post_transform = Transform3D::create_translation(-perspective_origin.x,
+                                                                     -perspective_origin.y,
+                                                                     0.0);
 
                 let perspective_matrix = create_perspective_matrix(length);
 
                 Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform))
             }
             Either::Second(values::None_) => {
                 None
             }
@@ -3094,19 +3094,19 @@ impl Overflow {
         }
     }
 
     pub fn union(&mut self, other: &Overflow) {
         self.scroll = self.scroll.union(&other.scroll);
         self.paint = self.paint.union(&other.paint);
     }
 
-    pub fn translate(&mut self, point: &Point2D<Au>) {
-        self.scroll = self.scroll.translate(point);
-        self.paint = self.paint.translate(point);
+    pub fn translate(&mut self, by: &Vector2D<Au>) {
+        self.scroll = self.scroll.translate(by);
+        self.paint = self.paint.translate(by);
     }
 }
 
 bitflags! {
     pub flags FragmentFlags: u8 {
         // TODO(stshine): find a better name since these flags can also be used for grid item.
         /// Whether this fragment represents a child in a row flex container.
         const IS_INLINE_FLEX_ITEM = 0b0000_0001,
@@ -3179,16 +3179,16 @@ impl Serialize for DebugId {
 // TODO(gw): The transforms spec says that perspective length must
 // be positive. However, there is some confusion between the spec
 // and browser implementations as to handling the case of 0 for the
 // perspective value. Until the spec bug is resolved, at least ensure
 // that a provided perspective value of <= 0.0 doesn't cause panics
 // and behaves as it does in other browsers.
 // See https://lists.w3.org/Archives/Public/www-style/2016Jan/0020.html for more details.
 #[inline]
-fn create_perspective_matrix(d: Au) -> Matrix4D<f32> {
+fn create_perspective_matrix(d: Au) -> Transform3D<f32> {
     let d = d.to_f32_px();
     if d <= 0.0 {
-        Matrix4D::identity()
+        Transform3D::identity()
     } else {
-        Matrix4D::create_perspective(d)
+        Transform3D::create_perspective(d)
     }
 }
--- a/servo/components/layout/inline.rs
+++ b/servo/components/layout/inline.rs
@@ -1595,53 +1595,53 @@ impl Flow for InlineFlow {
                         self.base.late_absolute_position_info;
 
                     let stacking_relative_position = self.base.stacking_relative_position;
                     if is_positioned {
                         let padding_box_origin = containing_block_positions.next().unwrap();
                         block_flow.base
                                   .late_absolute_position_info
                                   .stacking_relative_position_of_absolute_containing_block =
-                            stacking_relative_position + *padding_box_origin;
+                            *padding_box_origin + stacking_relative_position;
                     }
 
                     block_flow.base.stacking_relative_position =
-                        stacking_relative_content_box.origin;
+                        stacking_relative_content_box.origin.to_vector();
 
                     // Write the clip in our coordinate system into the child flow. (The kid will
                     // fix it up to be in its own coordinate system if necessary.)
                     block_flow.base.clip = self.base.clip.clone()
                 }
                 SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
                     let flow = FlowRef::deref_mut(&mut info.flow_ref);
                     let block_flow = flow.as_mut_block();
                     block_flow.base.late_absolute_position_info =
                         self.base.late_absolute_position_info;
 
                     block_flow.base.stacking_relative_position =
-                        stacking_relative_border_box.origin;
+                        stacking_relative_border_box.origin.to_vector();
 
                     // As above, this is in our coordinate system for now.
                     block_flow.base.clip = self.base.clip.clone()
                 }
                 SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
                     let flow = FlowRef::deref_mut(&mut info.flow_ref);
                     let block_flow = flow.as_mut_block();
                     block_flow.base.late_absolute_position_info =
                         self.base.late_absolute_position_info;
 
                     let stacking_relative_position = self.base.stacking_relative_position;
                     let padding_box_origin = containing_block_positions.next().unwrap();
                     block_flow.base
                               .late_absolute_position_info
                               .stacking_relative_position_of_absolute_containing_block =
-                        stacking_relative_position + *padding_box_origin;
+                        *padding_box_origin + stacking_relative_position;
 
                     block_flow.base.stacking_relative_position =
-                        stacking_relative_border_box.origin;
+                        stacking_relative_border_box.origin.to_vector();
 
                     // As above, this is in our coordinate system for now.
                     block_flow.base.clip = self.base.clip.clone()
                 }
                 _ => {}
             }
         }
 
@@ -1689,17 +1689,17 @@ impl Flow for InlineFlow {
             let relative_containing_block_mode =
                 self.base.early_absolute_position_info.relative_containing_block_mode;
             iterator.process(fragment,
                              level,
                              &fragment.stacking_relative_border_box(stacking_relative_position,
                                                                     relative_containing_block_size,
                                                                     relative_containing_block_mode,
                                                                     CoordinateSystem::Own)
-                                      .translate(stacking_context_position))
+                                      .translate(&stacking_context_position.to_vector()))
         }
     }
 
     fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) {
         for fragment in &mut self.fragments.fragments {
             (*mutator)(fragment)
         }
     }
--- a/servo/components/layout/list_item.rs
+++ b/servo/components/layout/list_item.rs
@@ -192,17 +192,17 @@ impl Flow for ListItemFlow {
                                                               .base
                                                               .early_absolute_position_info
                                                               .relative_containing_block_size,
                                                          self.block_flow
                                                              .base
                                                              .early_absolute_position_info
                                                              .relative_containing_block_mode,
                                                          CoordinateSystem::Own)
-                           .translate(stacking_context_position));
+                           .translate(&stacking_context_position.to_vector()));
             }
         }
     }
 
     fn mutate_fragments(&mut self, mutator: &mut FnMut(&mut Fragment)) {
         self.block_flow.mutate_fragments(mutator);
 
         for marker in &mut self.marker_fragments {
--- a/servo/components/layout/model.rs
+++ b/servo/components/layout/model.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/. */
 
 //! Borders, padding, and margins.
 
 #![deny(unsafe_code)]
 
 use app_units::Au;
-use euclid::{Matrix4D, SideOffsets2D, Size2D};
+use euclid::{Transform3D, SideOffsets2D, Size2D};
 use fragment::Fragment;
 use std::cmp::{max, min};
 use std::fmt;
 use style::computed_values::transform::ComputedMatrix;
 use style::logical_geometry::{LogicalMargin, WritingMode};
 use style::properties::ServoComputedValues;
 use style::values::computed::{BorderCornerRadius, LengthOrPercentageOrAuto};
 use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrNone};
@@ -504,22 +504,22 @@ pub fn specified_margin_from_style(style
     LogicalMargin::from_physical(writing_mode, SideOffsets2D::new(
         MaybeAuto::from_style(margin_style.margin_top, Au(0)).specified_or_zero(),
         MaybeAuto::from_style(margin_style.margin_right, Au(0)).specified_or_zero(),
         MaybeAuto::from_style(margin_style.margin_bottom, Au(0)).specified_or_zero(),
         MaybeAuto::from_style(margin_style.margin_left, Au(0)).specified_or_zero()))
 }
 
 pub trait ToGfxMatrix {
-    fn to_gfx_matrix(&self) -> Matrix4D<f32>;
+    fn to_gfx_matrix(&self) -> Transform3D<f32>;
 }
 
 impl ToGfxMatrix for ComputedMatrix {
-    fn to_gfx_matrix(&self) -> Matrix4D<f32> {
-        Matrix4D::row_major(
+    fn to_gfx_matrix(&self) -> Transform3D<f32> {
+        Transform3D::row_major(
             self.m11 as f32, self.m12 as f32, self.m13 as f32, self.m14 as f32,
             self.m21 as f32, self.m22 as f32, self.m23 as f32, self.m24 as f32,
             self.m31 as f32, self.m32 as f32, self.m33 as f32, self.m34 as f32,
             self.m41 as f32, self.m42 as f32, self.m43 as f32, self.m44 as f32)
     }
 }
 
 /// A min-size and max-size constraint. The constructor has a optional `border`
--- a/servo/components/layout/multicol.rs
+++ b/servo/components/layout/multicol.rs
@@ -6,18 +6,17 @@
 
 #![deny(unsafe_code)]
 
 use StyleArc;
 use app_units::Au;
 use block::BlockFlow;
 use context::LayoutContext;
 use display_list_builder::DisplayListBuildState;
-use euclid::Point2D;
-use euclid::Size2D;
+use euclid::{Point2D, Vector2D};
 use floats::FloatKind;
 use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx_traits::print_tree::PrintTree;
 use std::cmp::{min, max};
 use std::fmt;
 use std::sync::Arc;
 use style::logical_geometry::LogicalSize;
@@ -168,17 +167,17 @@ impl Flow for MulticolFlow {
     }
 
     fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
         self.block_flow.compute_absolute_position(layout_context);
         let pitch = LogicalSize::new(self.block_flow.base.writing_mode, self.column_pitch, Au(0));
         let pitch = pitch.to_physical(self.block_flow.base.writing_mode);
         for (i, child) in self.block_flow.base.children.iter_mut().enumerate() {
             let point = &mut mut_base(child).stacking_relative_position;
-            *point = *point + Size2D::new(pitch.width * i as i32, pitch.height * i as i32);
+            *point = *point + Vector2D::new(pitch.width * i as i32, pitch.height * i as i32);
         }
     }
 
     fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
         self.block_flow.update_late_computed_inline_position_if_necessary(inline_position)
     }
 
     fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
--- a/servo/components/layout/query.rs
+++ b/servo/components/layout/query.rs
@@ -2,19 +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/. */
 
 //! Utilities for querying the layout, as needed by the layout thread.
 
 use app_units::Au;
 use construct::ConstructionResult;
 use context::LayoutContext;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Point2D, Vector2D, Rect, Size2D};
 use flow::{self, Flow};
 use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
 use gfx::display_list::{DisplayItemMetadata, DisplayList, OpaqueNode, ScrollOffsetMap};
 use inline::LAST_FRAGMENT_OF_ELEMENT;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::PipelineId;
 use opaque_node::OpaqueNodeMethods;
 use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse};
@@ -608,17 +606,17 @@ impl FragmentBorderBoxIterator for Paren
                 (false, computed_values::position::T::static_, _) => false,
             };
 
             let parent_info = if is_valid_parent {
                 let border_width = fragment.border_width().to_physical(fragment.style.writing_mode);
 
                 Some(ParentBorderBoxInfo {
                     node_address: fragment.node,
-                    origin: border_box.origin + Point2D::new(border_width.left, border_width.top),
+                    origin: border_box.origin + Vector2D::new(border_width.left, border_width.top),
                 })
             } else {
                 None
             };
 
             self.parent_nodes.push(parent_info);
         }
     }
@@ -769,17 +767,17 @@ fn process_resolved_style_request_intern
             layout_el: <N::ConcreteThreadSafeLayoutNode as ThreadSafeLayoutNode>::ConcreteThreadSafeLayoutElement,
             layout_root: &mut Flow,
             requested_node: N,
             longhand_id: LonghandId) -> String {
         let maybe_data = layout_el.borrow_layout_data();
         let position = maybe_data.map_or(Point2D::zero(), |data| {
             match (*data).flow_construction_result {
                 ConstructionResult::Flow(ref flow_ref, _) =>
-                    flow::base(flow_ref.deref()).stacking_relative_position,
+                    flow::base(flow_ref.deref()).stacking_relative_position.to_point(),
                 // TODO(dzbarsky) search parents until we find node with a flow ref.
                 // https://github.com/servo/servo/issues/8307
                 _ => Point2D::zero()
             }
         });
         let property = match longhand_id {
             LonghandId::Bottom => PositionProperty::Bottom,
             LonghandId::Top => PositionProperty::Top,
@@ -847,17 +845,17 @@ pub fn process_offset_parent_query<N: La
         -> OffsetParentResponse {
     let mut iterator = ParentOffsetBorderBoxIterator::new(requested_node.opaque());
     sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
 
     let node_offset_box = iterator.node_offset_box;
     let parent_info = iterator.parent_nodes.into_iter().rev().filter_map(|info| info).next();
     match (node_offset_box, parent_info) {
         (Some(node_offset_box), Some(parent_info)) => {
-            let origin = node_offset_box.offset - parent_info.origin;
+            let origin = node_offset_box.offset - parent_info.origin.to_vector();
             let size = node_offset_box.rectangle.size;
             OffsetParentResponse {
                 node_address: Some(parent_info.node_address.to_untrusted_node_address()),
                 rect: Rect::new(origin, size),
             }
         }
         _ => {
             OffsetParentResponse::empty()
--- a/servo/components/layout/sequential.rs
+++ b/servo/components/layout/sequential.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/. */
 
 //! Implements sequential traversals over the DOM and flow trees.
 
 use app_units::Au;
 use context::LayoutContext;
 use display_list_builder::DisplayListBuildState;
-use euclid::point::Point2D;
+use euclid::{Point2D, Vector2D};
 use floats::SpeculatedFloatPlacement;
 use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
 use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
 use flow::IS_ABSOLUTELY_POSITIONED;
 use fragment::{FragmentBorderBoxIterator, CoordinateSystem};
 use generated_content::ResolveGeneratedContent;
 use incremental::RelayoutMode;
 use servo_config::opts;
@@ -104,26 +104,26 @@ pub fn iterate_through_flow_tree_fragmen
             stacking_context_position: &Point2D<Au>) {
         flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position);
 
         for kid in flow::mut_base(flow).child_iter_mut() {
             let mut stacking_context_position = *stacking_context_position;
             if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() {
                 stacking_context_position = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) +
                                             flow::base(kid).stacking_relative_position +
-                                            stacking_context_position;
+                                            stacking_context_position.to_vector();
                 let relative_position = kid.as_block()
                     .stacking_relative_position(CoordinateSystem::Own);
                 if let Some(matrix) = kid.as_block()
                        .fragment
                        .transform_matrix(&relative_position) {
-                    let transform_matrix = matrix.transform_point(&Point2D::zero());
+                    let transform_matrix = matrix.transform_point2d(&Point2D::zero());
                     stacking_context_position = stacking_context_position +
-                                                Point2D::new(Au::from_f32_px(transform_matrix.x),
-                                                             Au::from_f32_px(transform_matrix.y))
+                                                Vector2D::new(Au::from_f32_px(transform_matrix.x),
+                                                              Au::from_f32_px(transform_matrix.y))
                 }
             }
             doit(kid, level + 1, iterator, &stacking_context_position);
         }
     }
 
     doit(root, 0, iterator, &Point2D::zero());
 }
--- a/servo/components/layout/webrender_helpers.rs
+++ b/servo/components/layout/webrender_helpers.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // TODO(gw): This contains helper traits and implementations for converting Servo display lists
 //           into WebRender display lists. In the future, this step should be completely removed.
 //           This might be achieved by sharing types between WR and Servo display lists, or
 //           completely converting layout to directly generate WebRender display lists, for example.
 
 use app_units::Au;
-use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
+use euclid::{Point2D, Vector2D, Rect, SideOffsets2D, Size2D};
 use gfx::display_list::{BorderDetails, BorderRadii, BoxShadowClipMode, ClippingRegion};
 use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal, StackingContextType};
 use msg::constellation_msg::PipelineId;
 use style::computed_values::{image_rendering, mix_blend_mode, transform_style};
 use style::computed_values::filter::{self, Filter};
 use style::values::computed::BorderStyle;
 use webrender_traits::{self, DisplayListBuilder, ExtendMode};
 use webrender_traits::{LayoutTransform, ClipId, ClipRegionToken};
@@ -81,22 +81,32 @@ impl ToBoxShadowClipMode for BoxShadowCl
 trait ToSizeF {
     fn to_sizef(&self) -> webrender_traits::LayoutSize;
 }
 
 trait ToPointF {
     fn to_pointf(&self) -> webrender_traits::LayoutPoint;
 }
 
+trait ToVectorF {
+    fn to_vectorf(&self) -> webrender_traits::LayoutVector2D;
+}
+
 impl ToPointF for Point2D<Au> {
     fn to_pointf(&self) -> webrender_traits::LayoutPoint {
         webrender_traits::LayoutPoint::new(self.x.to_f32_px(), self.y.to_f32_px())
     }
 }
 
+impl ToVectorF for Vector2D<Au> {
+    fn to_vectorf(&self) -> webrender_traits::LayoutVector2D {
+        webrender_traits::LayoutVector2D::new(self.x.to_f32_px(), self.y.to_f32_px())
+    }
+}
+
 impl ToSizeF for Size2D<Au> {
     fn to_sizef(&self) -> webrender_traits::LayoutSize {
         webrender_traits::LayoutSize::new(self.width.to_f32_px(), self.height.to_f32_px())
     }
 }
 
 trait ToRectF {
     fn to_rectf(&self) -> webrender_traits::LayoutRect;
@@ -445,17 +455,17 @@ impl WebRenderDisplayItemConverter for D
             }
             DisplayItem::BoxShadow(ref item) => {
                 let rect = item.base.bounds.to_rectf();
                 let box_bounds = item.box_bounds.to_rectf();
                 let clip = item.base.clip.push_clip_region(builder);
                 builder.push_box_shadow(rect,
                                         clip,
                                         box_bounds,
-                                        item.offset.to_pointf(),
+                                        item.offset.to_vectorf(),
                                         item.color,
                                         item.blur_radius.to_f32_px(),
                                         item.spread_radius.to_f32_px(),
                                         item.border_radius.to_f32_px(),
                                         item.clip_mode.to_clip_mode());
             }
             DisplayItem::Iframe(ref item) => {
                 let rect = item.base.bounds.to_rectf();
--- a/servo/components/layout_thread/Cargo.toml
+++ b/servo/components/layout_thread/Cargo.toml
@@ -6,17 +6,17 @@ license = "MPL-2.0"
 publish = false
 
 [lib]
 name = "layout_thread"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4.1"
-euclid = "0.13"
+euclid = "0.14.4"
 fnv = "1.0"
 gfx = {path = "../gfx"}
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.4"
 ipc-channel = "0.7"
 layout = {path = "../layout"}
 layout_traits = {path = "../layout_traits"}
 lazy_static = "0.2"
--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -35,20 +35,17 @@ extern crate selectors;
 extern crate serde_json;
 extern crate servo_config;
 extern crate servo_geometry;
 extern crate servo_url;
 extern crate style;
 extern crate webrender_traits;
 
 use app_units::Au;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::Size2D;
+use euclid::{Point2D, Rect, Size2D, ScaleFactor};
 use fnv::FnvHashMap;
 use gfx::display_list::{OpaqueNode, WebRenderImageInfo};
 use gfx::font;
 use gfx::font_cache_thread::FontCacheThread;
 use gfx::font_context;
 use gfx_traits::{Epoch, node_id_from_clip_id};
 use heapsize::HeapSizeOf;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
@@ -905,17 +902,17 @@ impl LayoutThread {
         let writing_mode = flow::base(layout_root).writing_mode;
         let (metadata, sender) = (self.profiler_metadata(), self.time_profiler_chan.clone());
         profile(time::ProfilerCategory::LayoutDispListBuild,
                 metadata.clone(),
                 sender.clone(),
                 || {
             flow::mut_base(layout_root).stacking_relative_position =
                 LogicalPoint::zero(writing_mode).to_physical(writing_mode,
-                                                             self.viewport_size);
+                                                             self.viewport_size).to_vector();
 
             flow::mut_base(layout_root).clip = data.page_clip_rect;
 
             if flow::base(layout_root).restyle_damage.contains(REPOSITION) {
                 layout_root.traverse_preorder(&ComputeAbsolutePositions {
                     layout_context: layout_context
                 });
             }
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -36,17 +36,17 @@ canvas_traits = {path = "../canvas_trait
 caseless = "0.1.0"
 cookie = "0.6"
 cssparser = "0.14.0"
 deny_public_fields = {path = "../deny_public_fields"}
 devtools_traits = {path = "../devtools_traits"}
 dom_struct = {path = "../dom_struct"}
 domobject_derive = {path = "../domobject_derive"}
 encoding = "0.2"
-euclid = "0.13"
+euclid = "0.14.4"
 fnv = "1.0"
 gleam = "0.4"
 gfx_traits = {path = "../gfx_traits"}
 half = "1.0"
 heapsize = "0.4"
 heapsize_derive = "0.1"
 html5ever = {version = "0.17", features = ["heap_size", "unstable"]}
 hyper = "0.10"
@@ -58,17 +58,17 @@ jstraceable_derive = {path = "../jstrace
 lazy_static = "0.2"
 libc = "0.2"
 log = "0.3.5"
 mime = "0.2.1"
 mime_guess = "1.8.0"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 num-traits = "0.1.32"
-offscreen_gl_context = "0.8"
+offscreen_gl_context = { version = "0.9", features = ["serde"] }
 open = "1.1.1"
 parking_lot = "0.3"
 phf = "0.7.18"
 profile_traits = {path = "../profile_traits"}
 range = {path = "../range"}
 ref_filter_map = "1.0.1"
 ref_slice = "1.0"
 regex = "0.2"
--- a/servo/components/script/dom/bindings/trace.rs
+++ b/servo/components/script/dom/bindings/trace.rs
@@ -38,20 +38,18 @@ use dom::abstractworker::SharedRt;
 use dom::bindings::cell::DOMRefCell;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::refcounted::{Trusted, TrustedPromise};
 use dom::bindings::reflector::{DomObject, Reflector};
 use dom::bindings::str::{DOMString, USVString};
 use dom::bindings::utils::WindowProxyHandler;
 use dom::document::PendingRestyle;
 use encoding::types::EncodingRef;
-use euclid::{Matrix2D, Matrix4D, Point2D};
-use euclid::length::Length as EuclidLength;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, Size2D};
+use euclid::Length as EuclidLength;
 use html5ever::{Prefix, LocalName, Namespace, QualName};
 use html5ever::buffer_queue::BufferQueue;
 use html5ever::tendril::IncompleteUtf8;
 use hyper::header::Headers;
 use hyper::method::Method;
 use hyper::mime::Mime;
 use hyper::status::StatusCode;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
@@ -452,37 +450,44 @@ unsafe impl<T: Send> JSTraceable for Rec
 
 unsafe impl<T: Send> JSTraceable for Sender<T> {
     #[inline]
     unsafe fn trace(&self, _: *mut JSTracer) {
         // Do nothing
     }
 }
 
-unsafe impl JSTraceable for Matrix2D<f32> {
+unsafe impl JSTraceable for Transform2D<f32> {
     #[inline]
     unsafe fn trace(&self, _trc: *mut JSTracer) {
         // Do nothing
     }
 }
 
-unsafe impl JSTraceable for Matrix4D<f64> {
+unsafe impl JSTraceable for Transform3D<f64> {
     #[inline]
     unsafe fn trace(&self, _trc: *mut JSTracer) {
         // Do nothing
     }
 }
 
 unsafe impl JSTraceable for Point2D<f32> {
     #[inline]
     unsafe fn trace(&self, _trc: *mut JSTracer) {
         // Do nothing
     }
 }
 
+unsafe impl JSTraceable for Vector2D<f32> {
+    #[inline]
+    unsafe fn trace(&self, _trc: *mut JSTracer) {
+        // Do nothing
+    }
+}
+
 unsafe impl<T> JSTraceable for EuclidLength<u64, T> {
     #[inline]
     unsafe fn trace(&self, _trc: *mut JSTracer) {
         // Do nothing
     }
 }
 
 unsafe impl JSTraceable for Rect<Au> {
--- a/servo/components/script/dom/canvaspattern.rs
+++ b/servo/components/script/dom/canvaspattern.rs
@@ -4,17 +4,17 @@
 
 use canvas_traits::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle};
 use dom::bindings::codegen::Bindings::CanvasPatternBinding;
 use dom::bindings::js::Root;
 use dom::bindings::reflector::{Reflector, reflect_dom_object};
 use dom::canvasgradient::ToFillOrStrokeStyle;
 use dom::globalscope::GlobalScope;
 use dom_struct::dom_struct;
-use euclid::size::Size2D;
+use euclid::Size2D;
 
 // https://html.spec.whatwg.org/multipage/#canvaspattern
 #[dom_struct]
 pub struct CanvasPattern {
     reflector_: Reflector,
     surface_data: Vec<u8>,
     surface_size: Size2D<i32>,
     repeat_x: bool,
--- a/servo/components/script/dom/canvasrenderingcontext2d.rs
+++ b/servo/components/script/dom/canvasrenderingcontext2d.rs
@@ -29,20 +29,17 @@ use dom::canvasgradient::{CanvasGradient
 use dom::canvaspattern::CanvasPattern;
 use dom::globalscope::GlobalScope;
 use dom::htmlcanvaselement::HTMLCanvasElement;
 use dom::htmlcanvaselement::utils as canvas_utils;
 use dom::htmlimageelement::HTMLImageElement;
 use dom::imagedata::ImageData;
 use dom::node::{document_from_node, Node, NodeDamage, window_from_node};
 use dom_struct::dom_struct;
-use euclid::matrix2d::Matrix2D;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::image::base::PixelFormat;
 use net_traits::image_cache::ImageResponse;
 use num_traits::ToPrimitive;
 use script_traits::ScriptMsg as ConstellationMsg;
 use servo_url::ServoUrl;
 use std::{cmp, fmt};
 use std::cell::Cell;
@@ -77,17 +74,17 @@ struct CanvasContextState {
     global_composition: CompositionOrBlending,
     image_smoothing_enabled: bool,
     fill_style: CanvasFillOrStrokeStyle,
     stroke_style: CanvasFillOrStrokeStyle,
     line_width: f64,
     line_cap: LineCapStyle,
     line_join: LineJoinStyle,
     miter_limit: f64,
-    transform: Matrix2D<f32>,
+    transform: Transform2D<f32>,
     shadow_offset_x: f64,
     shadow_offset_y: f64,
     shadow_blur: f64,
     shadow_color: RGBA,
 }
 
 impl CanvasContextState {
     fn new() -> CanvasContextState {
@@ -97,17 +94,17 @@ impl CanvasContextState {
             global_composition: CompositionOrBlending::default(),
             image_smoothing_enabled: true,
             fill_style: CanvasFillOrStrokeStyle::Color(black),
             stroke_style: CanvasFillOrStrokeStyle::Color(black),
             line_width: 1.0,
             line_cap: LineCapStyle::Butt,
             line_join: LineJoinStyle::Miter,
             miter_limit: 10.0,
-            transform: Matrix2D::identity(),
+            transform: Transform2D::identity(),
             shadow_offset_x: 0.0,
             shadow_offset_y: 0.0,
             shadow_blur: 0.0,
             shadow_color: RGBA::transparent(),
         }
     }
 }
 
@@ -554,74 +551,74 @@ impl CanvasRenderingContext2DMethods for
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale
     fn Scale(&self, x: f64, y: f64) {
         if !(x.is_finite() && y.is_finite()) {
             return;
         }
 
         let transform = self.state.borrow().transform;
-        self.state.borrow_mut().transform = transform.pre_scaled(x as f32, y as f32);
+        self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32);
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate
     fn Rotate(&self, angle: f64) {
         if angle == 0.0 || !angle.is_finite() {
             return;
         }
 
         let (sin, cos) = (angle.sin(), angle.cos());
         let transform = self.state.borrow().transform;
         self.state.borrow_mut().transform = transform.pre_mul(
-            &Matrix2D::row_major(cos as f32, sin as f32,
+            &Transform2D::row_major(cos as f32, sin as f32,
                                  -sin as f32, cos as f32,
                                  0.0, 0.0));
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate
     fn Translate(&self, x: f64, y: f64) {
         if !(x.is_finite() && y.is_finite()) {
             return;
         }
 
         let transform = self.state.borrow().transform;
-        self.state.borrow_mut().transform = transform.pre_translated(x as f32, y as f32);
+        self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32));
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform
     fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
         if !(a.is_finite() && b.is_finite() && c.is_finite() &&
              d.is_finite() && e.is_finite() && f.is_finite()) {
             return;
         }
 
         let transform = self.state.borrow().transform;
         self.state.borrow_mut().transform = transform.pre_mul(
-            &Matrix2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32));
+            &Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32));
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform
     fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
         if !(a.is_finite() && b.is_finite() && c.is_finite() &&
              d.is_finite() && e.is_finite() && f.is_finite()) {
             return;
         }
 
         self.state.borrow_mut().transform =
-            Matrix2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32);
+            Transform2D::row_major(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32);
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
     fn ResetTransform(&self) {
-        self.state.borrow_mut().transform = Matrix2D::identity();
+        self.state.borrow_mut().transform = Transform2D::identity();
         self.update_transform()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
     fn GlobalAlpha(&self) -> f64 {
         let state = self.state.borrow();
         state.global_alpha
     }
@@ -1074,17 +1071,17 @@ impl CanvasRenderingContext2DMethods for
                      imagedata: &ImageData,
                      dx: Finite<f64>,
                      dy: Finite<f64>,
                      dirty_x: Finite<f64>,
                      dirty_y: Finite<f64>,
                      dirty_width: Finite<f64>,
                      dirty_height: Finite<f64>) {
         let data = imagedata.get_data_array();
-        let offset = Point2D::new(*dx, *dy);
+        let offset = Vector2D::new(*dx, *dy);
         let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64);
 
         let dirty_rect = Rect::new(Point2D::new(*dirty_x, *dirty_y),
                                    Size2D::new(*dirty_width, *dirty_height));
         let msg = CanvasMsg::Canvas2d(Canvas2dMsg::PutImageData(data,
                                                                 offset,
                                                                 image_data_size,
                                                                 dirty_rect));
--- a/servo/components/script/dom/document.rs
+++ b/servo/components/script/dom/document.rs
@@ -87,17 +87,17 @@ use dom::touchlist::TouchList;
 use dom::treewalker::TreeWalker;
 use dom::uievent::UIEvent;
 use dom::webglcontextevent::WebGLContextEvent;
 use dom::window::{ReflowReason, Window};
 use dom::windowproxy::WindowProxy;
 use dom_struct::dom_struct;
 use encoding::EncodingRef;
 use encoding::all::UTF_8;
-use euclid::point::Point2D;
+use euclid::{Point2D, Vector2D};
 use html5ever::{LocalName, QualName};
 use hyper::header::{Header, SetCookie};
 use hyper_serde::Serde;
 use ipc_channel::ipc::{self, IpcSender};
 use js::jsapi::{JSContext, JSObject, JSRuntime};
 use js::jsapi::JS_GetRuntime;
 use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
 use msg::constellation_msg::{BrowsingContextId, Key, KeyModifiers, KeyState, TopLevelBrowsingContextId};
@@ -860,17 +860,17 @@ impl Document {
                 }
             },
         };
 
         // If the target is an iframe, forward the event to the child document.
         if let Some(iframe) = el.downcast::<HTMLIFrameElement>() {
             if let Some(pipeline_id) = iframe.pipeline_id() {
                 let rect = iframe.upcast::<Element>().GetBoundingClientRect();
-                let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32);
+                let child_origin = Vector2D::new(rect.X() as f32, rect.Y() as f32);
                 let child_point = client_point - child_origin;
 
                 let event = CompositorEvent::MouseButtonEvent(mouse_event_type, button, child_point);
                 let event = ConstellationMsg::ForwardEvent(pipeline_id, event);
                 self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap();
             }
             return;
         }
@@ -1015,17 +1015,17 @@ impl Document {
                 }
             },
         };
 
         // If the target is an iframe, forward the event to the child document.
         if let Some(iframe) = el.downcast::<HTMLIFrameElement>() {
             if let Some(pipeline_id) = iframe.pipeline_id() {
                 let rect = iframe.upcast::<Element>().GetBoundingClientRect();
-                let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32);
+                let child_origin = Vector2D::new(rect.X() as f32, rect.Y() as f32);
                 let child_point = client_point - child_origin;
 
                 let event = CompositorEvent::TouchpadPressureEvent(child_point,
                                                                    pressure,
                                                                    phase_now);
                 let event = ConstellationMsg::ForwardEvent(pipeline_id, event);
                 self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap();
             }
@@ -1119,17 +1119,17 @@ impl Document {
         });
 
         // Send mousemove event to topmost target, and forward it if it's an iframe
         if let Some(ref new_target) = maybe_new_target {
             // If the target is an iframe, forward the event to the child document.
             if let Some(iframe) = new_target.downcast::<HTMLIFrameElement>() {
                 if let Some(pipeline_id) = iframe.pipeline_id() {
                     let rect = iframe.upcast::<Element>().GetBoundingClientRect();
-                    let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32);
+                    let child_origin = Vector2D::new(rect.X() as f32, rect.Y() as f32);
                     let child_point = client_point - child_origin;
 
                     let event = CompositorEvent::MouseMoveEvent(Some(child_point));
                     let event = ConstellationMsg::ForwardEvent(pipeline_id, event);
                     self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap();
                 }
                 return;
             }
@@ -1226,17 +1226,17 @@ impl Document {
                 }
             },
         };
 
         // If the target is an iframe, forward the event to the child document.
         if let Some(iframe) = el.downcast::<HTMLIFrameElement>() {
             if let Some(pipeline_id) = iframe.pipeline_id() {
                 let rect = iframe.upcast::<Element>().GetBoundingClientRect();
-                let child_origin = Point2D::new(rect.X() as f32, rect.Y() as f32);
+                let child_origin = Vector2D::new(rect.X() as f32, rect.Y() as f32);
                 let child_point = point - child_origin;
 
                 let event = CompositorEvent::TouchEvent(event_type, touch_id, child_point);
                 let event = ConstellationMsg::ForwardEvent(pipeline_id, event);
                 self.window.upcast::<GlobalScope>().constellation_chan().send(event).unwrap();
             }
             return TouchEventResult::Forwarded;
         }
--- a/servo/components/script/dom/dommatrix.rs
+++ b/servo/components/script/dom/dommatrix.rs
@@ -6,32 +6,32 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::codegen::Bindings::DOMMatrixReadOnlyBinding::DOMMatrixReadOnlyMethods;
 use dom::bindings::error::Fallible;
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::Root;
 use dom::bindings::reflector::reflect_dom_object;
 use dom::dommatrixreadonly::{dommatrixinit_to_matrix, DOMMatrixReadOnly, entries_to_matrix};
 use dom::globalscope::GlobalScope;
 use dom_struct::dom_struct;
-use euclid::Matrix4D;
+use euclid::Transform3D;
 
 
 #[dom_struct]
 pub struct DOMMatrix {
     parent: DOMMatrixReadOnly
 }
 
 impl DOMMatrix {
     #[allow(unrooted_must_root)]
-    pub fn new(global: &GlobalScope, is2D: bool, matrix: Matrix4D<f64>) -> Root<Self> {
+    pub fn new(global: &GlobalScope, is2D: bool, matrix: Transform3D<f64>) -> Root<Self> {
         let dommatrix = Self::new_inherited(is2D, matrix);
         reflect_dom_object(box dommatrix, global, Wrap)
     }
 
-    pub fn new_inherited(is2D: bool, matrix: Matrix4D<f64>) -> Self {
+    pub fn new_inherited(is2D: bool, matrix: Transform3D<f64>) -> Self {
         DOMMatrix {
             parent: DOMMatrixReadOnly::new_inherited(is2D, matrix)
         }
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-dommatrix
     pub fn Constructor(global: &GlobalScope) -> Fallible<Root<Self>> {
         Self::Constructor_(global, vec![1.0, 0.0, 0.0, 1.0, 0.0, 0.0])
--- a/servo/components/script/dom/dommatrixreadonly.rs
+++ b/servo/components/script/dom/dommatrixreadonly.rs
@@ -9,45 +9,45 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::error;
 use dom::bindings::error::Fallible;
 use dom::bindings::js::Root;
 use dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
 use dom::dommatrix::DOMMatrix;
 use dom::dompoint::DOMPoint;
 use dom::globalscope::GlobalScope;
 use dom_struct::dom_struct;
-use euclid::{Matrix4D, Point4D, Radians};
+use euclid::{Transform3D, Radians};
 use std::cell::{Cell, Ref};
 use std::f64;
 
 #[dom_struct]
 pub struct DOMMatrixReadOnly {
     reflector_: Reflector,
-    matrix: DOMRefCell<Matrix4D<f64>>,
+    matrix: DOMRefCell<Transform3D<f64>>,
     is2D: Cell<bool>,
 }
 
 impl DOMMatrixReadOnly {
     #[allow(unrooted_must_root)]
-    pub fn new(global: &GlobalScope, is2D: bool, matrix: Matrix4D<f64>) -> Root<Self> {
+    pub fn new(global: &GlobalScope, is2D: bool, matrix: Transform3D<f64>) -> Root<Self> {
         let dommatrix = Self::new_inherited(is2D, matrix);
         reflect_dom_object(box dommatrix, global, Wrap)
     }
 
-    pub fn new_inherited(is2D: bool, matrix: Matrix4D<f64>) -> Self {
+    pub fn new_inherited(is2D: bool, matrix: Transform3D<f64>) -> Self {
         DOMMatrixReadOnly {
             reflector_: Reflector::new(),
             matrix: DOMRefCell::new(matrix),
             is2D: Cell::new(is2D),
         }
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly
     pub fn Constructor(global: &GlobalScope) -> Fallible<Root<Self>> {
-        Ok(Self::new(global, true, Matrix4D::identity()))
+        Ok(Self::new(global, true, Transform3D::identity()))
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
     pub fn Constructor_(global: &GlobalScope, entries: Vec<f64>) -> Fallible<Root<Self>> {
         entries_to_matrix(&entries[..])
             .map(|(is2D, matrix)| {
                 Self::new(global, is2D, matrix)
             })
@@ -56,17 +56,17 @@ impl DOMMatrixReadOnly {
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-frommatrix
     pub fn FromMatrix(global: &GlobalScope, other: &DOMMatrixInit) -> Fallible<Root<Self>> {
         dommatrixinit_to_matrix(&other)
             .map(|(is2D, matrix)| {
                 Self::new(global, is2D, matrix)
             })
     }
 
-    pub fn matrix(&self) -> Ref<Matrix4D<f64>> {
+    pub fn matrix(&self) -> Ref<Transform3D<f64>> {
         self.matrix.borrow()
     }
 
     pub fn is_2d(&self) -> bool {
         self.is2D.get()
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-m11
@@ -178,17 +178,17 @@ impl DOMMatrixReadOnly {
             }
             // Step 4 in DOMMatrix.PreMultiplySelf
         })
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-translateself
     pub fn translate_self(&self, tx: f64, ty: f64, tz: f64) {
         // Step 1.
-        let translation = Matrix4D::create_translation(tx, ty, tz);
+        let translation = Transform3D::create_translation(tx, ty, tz);
         let mut matrix = self.matrix.borrow_mut();
         *matrix = translation.post_mul(&matrix);
         // Step 2.
         if tz != 0.0 {
             self.is2D.set(false);
         }
         // Step 3 in DOMMatrix.TranslateSelf
     }
@@ -197,17 +197,17 @@ impl DOMMatrixReadOnly {
     pub fn scale_self(&self, scaleX: f64, scaleY: Option<f64>, scaleZ: f64,
                       mut originX: f64, mut originY: f64, mut originZ: f64) {
         // Step 1.
         self.translate_self(originX, originY, originZ);
         // Step 2.
         let scaleY = scaleY.unwrap_or(scaleX);
         // Step 3.
         {
-            let scale3D = Matrix4D::create_scale(scaleX, scaleY, scaleZ);
+            let scale3D = Transform3D::create_scale(scaleX, scaleY, scaleZ);
             let mut matrix = self.matrix.borrow_mut();
             *matrix = scale3D.post_mul(&matrix);
         }
         // Step 4.
         originX = -originX;
         originY = -originY;
         originZ = -originZ;
         // Step 5.
@@ -220,17 +220,17 @@ impl DOMMatrixReadOnly {
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-scale3dself
     pub fn scale_3d_self(&self, scale: f64, originX: f64, originY: f64, originZ: f64) {
         // Step 1.
         self.translate_self(originX, originY, originZ);
         // Step 2.
         {
-            let scale3D = Matrix4D::create_scale(scale, scale, scale);
+            let scale3D = Transform3D::create_scale(scale, scale, scale);
             let mut matrix = self.matrix.borrow_mut();
             *matrix = scale3D.post_mul(&matrix);
         }
         // Step 3.
         self.translate_self(-originX, -originY, -originZ);
         // Step 4.
         if scale != 1.0 {
             self.is2D.set(false);
@@ -251,88 +251,88 @@ impl DOMMatrixReadOnly {
         // Step 3.
         let rotZ = rotZ.unwrap_or(0.0);
         // Step 4.
         if rotX != 0.0 || rotY != 0.0 {
             self.is2D.set(false);
         }
         if rotZ != 0.0 {
             // Step 5.
-            let rotation = Matrix4D::create_rotation(0.0, 0.0, 1.0, Radians::new(rotZ.to_radians()));
+            let rotation = Transform3D::create_rotation(0.0, 0.0, 1.0, Radians::new(rotZ.to_radians()));
             let mut matrix = self.matrix.borrow_mut();
             *matrix = rotation.post_mul(&matrix);
         }
         if rotY != 0.0 {
             // Step 6.
-            let rotation = Matrix4D::create_rotation(0.0, 1.0, 0.0, Radians::new(rotY.to_radians()));
+            let rotation = Transform3D::create_rotation(0.0, 1.0, 0.0, Radians::new(rotY.to_radians()));
             let mut matrix = self.matrix.borrow_mut();
             *matrix = rotation.post_mul(&matrix);
         }
         if rotX != 0.0 {
             // Step 7.
-            let rotation = Matrix4D::create_rotation(1.0, 0.0, 0.0, Radians::new(rotX.to_radians()));
+            let rotation = Transform3D::create_rotation(1.0, 0.0, 0.0, Radians::new(rotX.to_radians()));
             let mut matrix = self.matrix.borrow_mut();
             *matrix = rotation.post_mul(&matrix);
         }
         // Step 8 in DOMMatrix.RotateSelf
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotatefromvectorself
     pub fn rotate_from_vector_self(&self, x: f64, y: f64) {
         // don't do anything when the rotation angle is zero or undefined
         if y != 0.0 || x < 0.0 {
             // Step 1.
             let rotZ = Radians::new(f64::atan2(y, x));
-            let rotation = Matrix4D::create_rotation(0.0, 0.0, 1.0, rotZ);
+            let rotation = Transform3D::create_rotation(0.0, 0.0, 1.0, rotZ);
             let mut matrix = self.matrix.borrow_mut();
             *matrix = rotation.post_mul(&matrix);
         }
         // Step 2 in DOMMatrix.RotateFromVectorSelf
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-rotateaxisangleself
     pub fn rotate_axis_angle_self(&self, x: f64, y: f64, z: f64, angle: f64) {
         // Step 1.
         let (norm_x, norm_y, norm_z) = normalize_point(x, y, z);
-        let rotation = Matrix4D::create_rotation(norm_x, norm_y, norm_z, Radians::new(angle.to_radians()));
+        let rotation = Transform3D::create_rotation(norm_x, norm_y, norm_z, Radians::new(angle.to_radians()));
         let mut matrix = self.matrix.borrow_mut();
         *matrix = rotation.post_mul(&matrix);
         // Step 2.
         if x != 0.0 || y != 0.0 {
             self.is2D.set(false);
         }
         // Step 3 in DOMMatrix.RotateAxisAngleSelf
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-skewxself
     pub fn skew_x_self(&self, sx: f64) {
         // Step 1.
-        let skew = Matrix4D::create_skew(Radians::new(sx.to_radians()), Radians::new(0.0));
+        let skew = Transform3D::create_skew(Radians::new(sx.to_radians()), Radians::new(0.0));
         let mut matrix = self.matrix.borrow_mut();
         *matrix = skew.post_mul(&matrix);
         // Step 2 in DOMMatrix.SkewXSelf
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-skewyself
     pub fn skew_y_self(&self, sy: f64) {
         // Step 1.
-        let skew = Matrix4D::create_skew(Radians::new(0.0), Radians::new(sy.to_radians()));
+        let skew = Transform3D::create_skew(Radians::new(0.0), Radians::new(sy.to_radians()));
         let mut matrix = self.matrix.borrow_mut();
         *matrix = skew.post_mul(&matrix);
         // Step 2 in DOMMatrix.SkewYSelf
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrix-invertself
     pub fn invert_self(&self) {
         let mut matrix = self.matrix.borrow_mut();
         // Step 1.
         *matrix = matrix.inverse().unwrap_or_else(|| {
             // Step 2.
             self.is2D.set(false);
-            Matrix4D::row_major(f64::NAN, f64::NAN, f64::NAN, f64::NAN,
+            Transform3D::row_major(f64::NAN, f64::NAN, f64::NAN, f64::NAN,
                                 f64::NAN, f64::NAN, f64::NAN, f64::NAN,
                                 f64::NAN, f64::NAN, f64::NAN, f64::NAN,
                                 f64::NAN, f64::NAN, f64::NAN, f64::NAN)
         })
         // Step 3 in DOMMatrix.InvertSelf
     }
 }
 
@@ -508,86 +508,91 @@ impl DOMMatrixReadOnlyMethods for DOMMat
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-multiply
     fn Multiply(&self, other: &DOMMatrixInit) -> Fallible<Root<DOMMatrix>> {
         DOMMatrix::from_readonly(&self.global(), self).MultiplySelf(&other)
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipx
     fn FlipX(&self) -> Root<DOMMatrix> {
         let is2D = self.is2D.get();
-        let flip = Matrix4D::row_major(-1.0, 0.0, 0.0, 0.0,
+        let flip = Transform3D::row_major(-1.0, 0.0, 0.0, 0.0,
                                         0.0, 1.0, 0.0, 0.0,
                                         0.0, 0.0, 1.0, 0.0,
                                         0.0, 0.0, 0.0, 1.0);
         let matrix = flip.post_mul(&self.matrix.borrow());
         DOMMatrix::new(&self.global(), is2D, matrix)
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-flipy
     fn FlipY(&self) -> Root<DOMMatrix> {
         let is2D = self.is2D.get();
-        let flip = Matrix4D::row_major(1.0,  0.0, 0.0, 0.0,
+        let flip = Transform3D::row_major(1.0,  0.0, 0.0, 0.0,
                                        0.0, -1.0, 0.0, 0.0,
                                        0.0,  0.0, 1.0, 0.0,
                                        0.0,  0.0, 0.0, 1.0);
         let matrix = flip.post_mul(&self.matrix.borrow());
         DOMMatrix::new(&self.global(), is2D, matrix)
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-inverse
     fn Inverse(&self) -> Root<DOMMatrix> {
         DOMMatrix::from_readonly(&self.global(), self).InvertSelf()
     }
 
     // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-transformpoint
     fn TransformPoint(&self, point: &DOMPointInit) -> Root<DOMPoint> {
-        let matrix = self.matrix.borrow();
-        let result = matrix.transform_point4d(&Point4D::new(point.x, point.y, point.z, point.w));
-        DOMPoint::new(
-            &self.global(),
-            result.x as f64,
-            result.y as f64,
-            result.z as f64,
-            result.w as f64)
+        // Euclid always normalizes the homogeneous coordinate which is usually the right
+        // thing but may (?) not be compliant with the CSS matrix spec (or at least is
+        // probably not the behavior web authors will expect even if it is mathematically
+        // correct in the context of geometry computations).
+        // Since this is the only place where this is needed, better implement it here
+        // than in euclid (which does not have a notion of 4d points).
+        let mat = self.matrix.borrow();
+        let x = point.x * mat.m11 + point.y * mat.m21 + point.z * mat.m31 + point.w * mat.m41;
+        let y = point.x * mat.m12 + point.y * mat.m22 + point.z * mat.m32 + point.w * mat.m42;
+        let z = point.x * mat.m13 + point.y * mat.m23 + point.z * mat.m33 + point.w * mat.m43;
+        let w = point.x * mat.m14 + point.y * mat.m24 + point.z * mat.m34 + point.w * mat.m44;
+
+        DOMPoint::new(&self.global(), x, y, z, w)
     }
 }
 
 
 // https://drafts.fxtf.org/geometry-1/#create-a-2d-matrix
-fn create_2d_matrix(entries: &[f64]) -> Matrix4D<f64> {
-    Matrix4D::row_major(entries[0], entries[1], 0.0, 0.0,
+fn create_2d_matrix(entries: &[f64]) -> Transform3D<f64> {
+    Transform3D::row_major(entries[0], entries[1], 0.0, 0.0,
                         entries[2], entries[3], 0.0, 0.0,
                         0.0,        0.0,        1.0, 0.0,
                         entries[4], entries[5], 0.0, 1.0)
 }
 
 
 // https://drafts.fxtf.org/geometry-1/#create-a-3d-matrix
-fn create_3d_matrix(entries: &[f64]) -> Matrix4D<f64> {
-    Matrix4D::row_major(entries[0],  entries[1],  entries[2],  entries[3],
+fn create_3d_matrix(entries: &[f64]) -> Transform3D<f64> {
+    Transform3D::row_major(entries[0],  entries[1],  entries[2],  entries[3],
                         entries[4],  entries[5],  entries[6],  entries[7],
                         entries[8],  entries[9],  entries[10], entries[11],
                         entries[12], entries[13], entries[14], entries[15])
 }
 
 // https://drafts.fxtf.org/geometry-1/#dom-dommatrixreadonly-dommatrixreadonly-numbersequence
-pub fn entries_to_matrix(entries: &[f64]) -> Fallible<(bool, Matrix4D<f64>)> {
+pub fn entries_to_matrix(entries: &[f64]) -> Fallible<(bool, Transform3D<f64>)> {
     if entries.len() == 6 {
         Ok((true, create_2d_matrix(&entries)))
     } else if entries.len() == 16 {
         Ok((false, create_3d_matrix(&entries)))
     } else {
         let err_msg = format!("Expected 6 or 16 entries, but found {}.", entries.len());
         Err(error::Error::Type(err_msg.to_owned()))
     }
 }
 
 
 // https://drafts.fxtf.org/geometry-1/#validate-and-fixup
-pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Matrix4D<f64>)> {
+pub fn dommatrixinit_to_matrix(dict: &DOMMatrixInit) -> Fallible<(bool, Transform3D<f64>)> {
     // Step 1.
     if dict.a.is_some() && dict.m11.is_some() && dict.a.unwrap() != dict.m11.unwrap() ||
        dict.b.is_some() && dict.m12.is_some() && dict.b.unwrap() != dict.m12.unwrap() ||
        dict.c.is_some() && dict.m21.is_some() && dict.c.unwrap() != dict.m21.unwrap() ||
        dict.d.is_some() && dict.m22.is_some() && dict.d.unwrap() != dict.m22.unwrap() ||
        dict.e.is_some() && dict.m41.is_some() && dict.e.unwrap() != dict.m41.unwrap() ||
        dict.f.is_some() && dict.m42.is_some() && dict.f.unwrap() != dict.m42.unwrap() ||
        dict.is2D.is_some() && dict.is2D.unwrap() &&
@@ -616,17 +621,17 @@ pub fn dommatrixinit_to_matrix(dict: &DO
              dict.m24 != 0.0 || dict.m34 != 0.0 ||
              dict.m33 != 1.0 || dict.m44 != 1.0) {
                  is2D = Some(false);
         }
         // Step 9.
         if is2D.is_none() {
             is2D = Some(true);
         }
-        let matrix = Matrix4D::row_major(m11,      m12,      dict.m13, dict.m14,
+        let matrix = Transform3D::row_major(m11,      m12,      dict.m13, dict.m14,
                                          m21,      m22,      dict.m23, dict.m24,
                                          dict.m31, dict.m32, dict.m33, dict.m34,
                                          m41,      m42,      dict.m43, dict.m44);
         Ok((is2D.unwrap(), matrix))
     }
 }
 
 
--- a/servo/components/script/dom/eventsource.rs
+++ b/servo/components/script/dom/eventsource.rs
@@ -11,17 +11,17 @@ use dom::bindings::js::Root;
 use dom::bindings::refcounted::Trusted;
 use dom::bindings::reflector::{DomObject, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::event::Event;
 use dom::eventtarget::EventTarget;
 use dom::globalscope::GlobalScope;
 use dom::messageevent::MessageEvent;
 use dom_struct::dom_struct;
-use euclid::length::Length;
+use euclid::Length;
 use hyper::header::{Accept, qitem};
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
 use js::conversions::ToJSValConvertible;
 use js::jsapi::JSAutoCompartment;
 use js::jsval::UndefinedValue;
 use mime::{Mime, TopLevel, SubLevel};
 use net_traits::{CoreResourceMsg, FetchMetadata, FetchResponseMsg, FetchResponseListener, NetworkError};
--- a/servo/components/script/dom/htmlareaelement.rs
+++ b/servo/components/script/dom/htmlareaelement.rs
@@ -14,17 +14,17 @@ use dom::domtokenlist::DOMTokenList;
 use dom::element::Element;
 use dom::event::Event;
 use dom::eventtarget::EventTarget;
 use dom::htmlanchorelement::follow_hyperlink;
 use dom::htmlelement::HTMLElement;
 use dom::node::{Node, document_from_node};
 use dom::virtualmethods::VirtualMethods;
 use dom_struct::dom_struct;
-use euclid::point::Point2D;
+use euclid::Point2D;
 use html5ever::{LocalName, Prefix};
 use net_traits::ReferrerPolicy;
 use std::default::Default;
 use std::f32;
 use style::attr::AttrValue;
 
 #[derive(PartialEq)]
 #[derive(Debug)]
--- a/servo/components/script/dom/htmlcanvaselement.rs
+++ b/servo/components/script/dom/htmlcanvaselement.rs
@@ -21,17 +21,17 @@ use dom::canvasrenderingcontext2d::{Canv
 use dom::document::Document;
 use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
 use dom::globalscope::GlobalScope;
 use dom::htmlelement::HTMLElement;
 use dom::node::{Node, window_from_node};
 use dom::virtualmethods::VirtualMethods;
 use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext};
 use dom_struct::dom_struct;
-use euclid::size::Size2D;
+use euclid::Size2D;
 use html5ever::{LocalName, Prefix};
 use image::ColorType;
 use image::png::PNGEncoder;
 use ipc_channel::ipc::{self, IpcSender};
 use js::error::throw_type_error;
 use js::jsapi::{HandleValue, JSContext};
 use offscreen_gl_context::GLContextAttributes;
 use script_layout_interface::HTMLCanvasData;
--- a/servo/components/script/dom/htmlimageelement.rs
+++ b/servo/components/script/dom/htmlimageelement.rs
@@ -30,17 +30,17 @@ use dom::htmlformelement::{FormControl, 
 use dom::htmlmapelement::HTMLMapElement;
 use dom::mouseevent::MouseEvent;
 use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
 use dom::progressevent::ProgressEvent;
 use dom::values::UNSIGNED_LONG_MAX;
 use dom::virtualmethods::VirtualMethods;
 use dom::window::Window;
 use dom_struct::dom_struct;
-use euclid::point::Point2D;
+use euclid::Point2D;
 use html5ever::{LocalName, Prefix};
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
 use microtask::{Microtask, MicrotaskRunnable};
 use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg};
 use net_traits::image::base::{Image, ImageMetadata};
 use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable};
 use net_traits::image_cache::{ImageResponder, ImageResponse, ImageState, PendingImageId};
--- a/servo/components/script/dom/imagedata.rs
+++ b/servo/components/script/dom/imagedata.rs
@@ -5,17 +5,17 @@
 use core::nonzero::NonZero;
 use dom::bindings::codegen::Bindings::ImageDataBinding;
 use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
 use dom::bindings::error::{Fallible, Error};
 use dom::bindings::js::Root;
 use dom::bindings::reflector::{Reflector, reflect_dom_object};
 use dom::globalscope::GlobalScope;
 use dom_struct::dom_struct;
-use euclid::size::Size2D;
+use euclid::Size2D;
 use js::jsapi::{Heap, JSContext, JSObject};
 use js::rust::Runtime;
 use js::typedarray::{Uint8ClampedArray, CreateWith};
 use std::default::Default;
 use std::ptr;
 use std::vec::Vec;
 
 #[dom_struct]
--- a/servo/components/script/dom/node.rs
+++ b/servo/components/script/dom/node.rs
@@ -51,19 +51,17 @@ use dom::mutationobserver::{Mutation, Mu
 use dom::nodelist::NodeList;
 use dom::processinginstruction::ProcessingInstruction;
 use dom::range::WeakRangeVec;
 use dom::svgsvgelement::{SVGSVGElement, LayoutSVGSVGElementHelpers};
 use dom::text::Text;
 use dom::virtualmethods::{VirtualMethods, vtable_for};
 use dom::window::Window;
 use dom_struct::dom_struct;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Point2D, Vector2D, Rect, Size2D};
 use heapsize::{HeapSizeOf, heap_size_of};
 use html5ever::{Prefix, Namespace, QualName};
 use js::jsapi::{JSContext, JSObject, JSRuntime};
 use libc::{self, c_void, uintptr_t};
 use msg::constellation_msg::{BrowsingContextId, PipelineId};
 use ref_slice::ref_slice;
 use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
 use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
@@ -607,17 +605,17 @@ impl Node {
                                        Size2D::new(max(window.InnerWidth(), scroll_area.size.width),
                                                    max(window.InnerHeight(), scroll_area.size.height)))
             },
             // Step 9
             _ => scroll_area
         }
     }
 
-    pub fn scroll_offset(&self) -> Point2D<f32> {
+    pub fn scroll_offset(&self) -> Vector2D<f32> {
         let document = self.owner_doc();
         let window = document.window();
         window.scroll_offset_query(self)
     }
 
     // https://dom.spec.whatwg.org/#dom-childnode-before
     pub fn before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
         // Step 1.
--- a/servo/components/script/dom/webglrenderingcontext.rs
+++ b/servo/components/script/dom/webglrenderingcontext.rs
@@ -35,17 +35,17 @@ use dom::webglframebuffer::WebGLFramebuf
 use dom::webglprogram::WebGLProgram;
 use dom::webglrenderbuffer::WebGLRenderbuffer;
 use dom::webglshader::WebGLShader;
 use dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat;
 use dom::webgltexture::{TexParameterValue, WebGLTexture};
 use dom::webgluniformlocation::WebGLUniformLocation;
 use dom::window::Window;
 use dom_struct::dom_struct;
-use euclid::size::Size2D;
+use euclid::Size2D;
 use half::f16;
 use ipc_channel::ipc::{self, IpcSender};
 use js::conversions::ConversionBehavior;
 use js::jsapi::{JSContext, JSObject, Type, Rooted};
 use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
 use js::typedarray::{TypedArray, TypedArrayElement, Float32, Int32};
 use net_traits::image::base::PixelFormat;
 use net_traits::image_cache::ImageResponse;
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -48,17 +48,17 @@ use dom::performance::Performance;
 use dom::promise::Promise;
 use dom::screen::Screen;
 use dom::storage::Storage;
 use dom::testrunner::TestRunner;
 use dom::windowproxy::WindowProxy;
 use dom::worklet::Worklet;
 use dom::workletglobalscope::WorkletGlobalScopeType;
 use dom_struct::dom_struct;
-use euclid::{Point2D, Rect, Size2D};
+use euclid::{Point2D, Vector2D, Rect, Size2D};
 use fetch;
 use ipc_channel::ipc::{self, IpcSender};
 use ipc_channel::router::ROUTER;
 use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext};
 use js::jsapi::{JS_GC, JS_GetRuntime};
 use js::jsval::UndefinedValue;
 use js::rust::Runtime;
 use layout_image::fetch_image_for_layout;
@@ -250,17 +250,17 @@ pub struct Window {
 
     /// A flag to prevent async events from attempting to interact with this window.
     #[ignore_heap_size_of = "defined in std"]
     ignore_further_async_events: DOMRefCell<Arc<AtomicBool>>,
 
     error_reporter: CSSErrorReporter,
 
     /// A list of scroll offsets for each scrollable element.
-    scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Point2D<f32>>>,
+    scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Vector2D<f32>>>,
 
     /// All the MediaQueryLists we need to update
     media_query_lists: WeakMediaQueryListVec,
 
     test_runner: MutNullableJS<TestRunner>,
 
     /// A handle for communicating messages to the webvr thread, if available.
     #[ignore_heap_size_of = "channels are hard"]
@@ -360,17 +360,17 @@ impl Window {
 
     pub fn css_error_reporter(&self) -> &ParseErrorReporter {
         &self.error_reporter
     }
 
     /// Sets a new list of scroll offsets.
     ///
     /// This is called when layout gives us new ones and WebRender is in use.
-    pub fn set_scroll_offsets(&self, offsets: HashMap<UntrustedNodeAddress, Point2D<f32>>) {
+    pub fn set_scroll_offsets(&self, offsets: HashMap<UntrustedNodeAddress, Vector2D<f32>>) {
         *self.scroll_offsets.borrow_mut() = offsets
     }
 
     pub fn current_viewport(&self) -> Rect<Au> {
         self.current_viewport.clone().get()
     }
 
     pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
@@ -1150,17 +1150,17 @@ impl Window {
                 })
             }
             ScrollBehavior::Instant => false,
             ScrollBehavior::Smooth => true
         };
 
         self.layout_chan.send(Msg::UpdateScrollStateFromScript(ScrollState {
             scroll_root_id: scroll_root_id,
-            scroll_offset: Point2D::new(-x, -y),
+            scroll_offset: Vector2D::new(-x, -y),
         })).unwrap();
 
         // TODO (farodin91): Raise an event to stop the current_viewport
         self.update_viewport_for_scroll(x, y);
 
         let global_scope = self.upcast::<GlobalScope>();
         let message = ConstellationMsg::ScrollFragmentPoint(scroll_root_id, point, smooth);
         global_scope.constellation_chan().send(message).unwrap();
@@ -1444,31 +1444,31 @@ impl Window {
         // *must* issue a reflow.
         assert!(self.reflow(ReflowGoal::ForScriptQuery,
                             ReflowQueryType::NodeOverflowQuery(node),
                             ReflowReason::Query));
 
         self.layout_rpc.node_overflow().0.unwrap()
     }
 
-    pub fn scroll_offset_query(&self, node: &Node) -> Point2D<f32> {
+    pub fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32> {
         let mut node = Root::from_ref(node);
         loop {
             if let Some(scroll_offset) = self.scroll_offsets
                                              .borrow()
                                              .get(&node.to_untrusted_node_address()) {
                 return *scroll_offset
             }
             node = match node.GetParentNode() {
                 Some(node) => node,
                 None => break,
             }
         }
-        let offset = self.current_viewport.get().origin;
-        Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px())
+        let vp_origin = self.current_viewport.get().origin;
+        Vector2D::new(vp_origin.x.to_f32_px(), vp_origin.y.to_f32_px())
     }
 
     // https://drafts.csswg.org/cssom-view/#dom-element-scroll
     pub fn scroll_node(&self,
                        node: TrustedNodeAddress,
                        x_: f64,
                        y_: f64,
                        behavior: ScrollBehavior) {
--- a/servo/components/script/dom/xmlhttprequest.rs
+++ b/servo/components/script/dom/xmlhttprequest.rs
@@ -35,17 +35,17 @@ use dom::urlsearchparams::URLSearchParam
 use dom::window::Window;
 use dom::workerglobalscope::WorkerGlobalScope;
 use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
 use dom::xmlhttprequestupload::XMLHttpRequestUpload;
 use dom_struct::dom_struct;
 use encoding::all::UTF_8;
 use encoding::label::encoding_from_whatwg_label;
 use encoding::types::{DecoderTrap, EncoderTrap, Encoding, EncodingRef};
-use euclid::length::Length;
+use euclid::Length;
 use html5ever::serialize;
 use html5ever::serialize::SerializeOpts;
 use hyper::header::{ContentLength, ContentType, ContentEncoding};
 use hyper::header::Headers;
 use hyper::method::Method;
 use hyper::mime::{self, Attr as MimeAttr, Mime, Value as MimeValue};
 use hyper_serde::Serde;
 use ipc_channel::ipc;
--- a/servo/components/script/script_thread.rs
+++ b/servo/components/script/script_thread.rs
@@ -53,18 +53,17 @@ use dom::serviceworkerregistration::Serv
 use dom::servoparser::{ParserContext, ServoParser};
 use dom::transitionevent::TransitionEvent;
 use dom::uievent::UIEvent;
 use dom::window::{ReflowReason, Window};
 use dom::windowproxy::WindowProxy;
 use dom::worker::TrustedWorkerAddress;
 use dom::worklet::WorkletThreadPool;
 use dom::workletglobalscope::WorkletGlobalScopeInit;
-use euclid::Rect;
-use euclid::point::Point2D;
+use euclid::{Point2D, Vector2D, Rect};
 use hyper::header::{ContentType, HttpDate, Headers, LastModified};
 use hyper::header::ReferrerPolicy as ReferrerPolicyHeader;
 use hyper::mime::{Mime, SubLevel, TopLevel};
 use hyper_serde::Serde;
 use ipc_channel::ipc::{self, IpcSender};
 use ipc_channel::router::ROUTER;
 use js::glue::GetWindowProxyClass;
 use js::jsapi::{JSAutoCompartment, JSContext, JS_SetWrapObjectCallbacks};
@@ -1334,29 +1333,28 @@ impl ScriptThread {
         if loads.iter().any(|load| load.pipeline_id == id) {
             return;
         }
         warn!("Page rect message sent to nonexistent pipeline");
     }
 
     fn handle_set_scroll_state(&self,
                                id: PipelineId,
-                               scroll_states: &[(UntrustedNodeAddress, Point2D<f32>)]) {
+                               scroll_states: &[(UntrustedNodeAddress, Vector2D<f32>)]) {
         let window = match { self.documents.borrow().find_window(id) } {
             Some(window) => window,
             None => return warn!("Set scroll state message sent to nonexistent pipeline: {:?}", id),
         };
 
         let mut scroll_offsets = HashMap::new();
         for &(node_address, ref scroll_offset) in scroll_states {
             if node_address == UntrustedNodeAddress(ptr::null()) {
                 window.update_viewport_for_scroll(-scroll_offset.x, -scroll_offset.y);
             } else {
-                scroll_offsets.insert(node_address,
-                                      Point2D::new(-scroll_offset.x, -scroll_offset.y));
+                scroll_offsets.insert(node_address, -*scroll_offset);
             }
         }
         window.set_scroll_offsets(scroll_offsets)
     }
 
     fn handle_new_layout(&self, new_layout_info: NewLayoutInfo, origin: MutableOrigin) {
         let NewLayoutInfo {
             parent_info,
--- a/servo/components/script/timers.rs
+++ b/servo/components/script/timers.rs
@@ -7,17 +7,17 @@ use dom::bindings::cell::DOMRefCell;
 use dom::bindings::codegen::Bindings::FunctionBinding::Function;
 use dom::bindings::reflector::DomObject;
 use dom::bindings::str::DOMString;
 use dom::document::FakeRequestAnimationFrameCallback;
 use dom::eventsource::EventSourceTimeoutCallback;
 use dom::globalscope::GlobalScope;
 use dom::testbinding::TestBindingCallback;
 use dom::xmlhttprequest::XHRTimeoutCallback;
-use euclid::length::Length;
+use euclid::Length;
 use heapsize::HeapSizeOf;
 use ipc_channel::ipc::IpcSender;
 use js::jsapi::{HandleValue, Heap};
 use js::jsval::{JSVal, UndefinedValue};
 use script_traits::{MsDuration, precise_time_ms};
 use script_traits::{TimerEvent, TimerEventId, TimerEventRequest};
 use script_traits::{TimerSchedulerMsg, TimerSource};
 use servo_config::prefs::PREFS;
--- a/servo/components/script/webdriver_handlers.rs
+++ b/servo/components/script/webdriver_handlers.rs
@@ -17,19 +17,17 @@ use dom::bindings::js::Root;
 use dom::bindings::str::DOMString;
 use dom::element::Element;
 use dom::globalscope::GlobalScope;
 use dom::htmlelement::HTMLElement;
 use dom::htmliframeelement::HTMLIFrameElement;
 use dom::htmlinputelement::HTMLInputElement;
 use dom::htmloptionelement::HTMLOptionElement;
 use dom::node::{Node, window_from_node};
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::size::Size2D;
+use euclid::{Point2D, Rect, Size2D};
 use hyper_serde::Serde;
 use ipc_channel::ipc::{self, IpcSender};
 use js::jsapi::{HandleValue, JSContext};
 use js::jsval::UndefinedValue;
 use msg::constellation_msg::BrowsingContextId;
 use msg::constellation_msg::PipelineId;
 use net_traits::CookieSource::{HTTP, NonHTTP};
 use net_traits::CoreResourceMsg::{GetCookiesDataForUrl, SetCookieForUrl};
--- a/servo/components/script_layout_interface/Cargo.toml
+++ b/servo/components/script_layout_interface/Cargo.toml
@@ -9,17 +9,17 @@ publish = false
 name = "script_layout_interface"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4.1"
 atomic_refcell = "0.1"
 canvas_traits = {path = "../canvas_traits"}
 cssparser = "0.14.0"
-euclid = "0.13"
+euclid = "0.14.4"
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.4"
 heapsize_derive = "0.1"
 html5ever = "0.17"
 ipc-channel = "0.7"
 libc = "0.2"
 log = "0.3.5"
 msg = {path = "../msg"}
--- a/servo/components/script_layout_interface/message.rs
+++ b/servo/components/script_layout_interface/message.rs
@@ -1,16 +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 {OpaqueStyleAndLayoutData, TrustedNodeAddress, PendingImage};
 use app_units::Au;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
+use euclid::{Point2D, Rect};
 use gfx_traits::Epoch;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use msg::constellation_msg::PipelineId;
 use net_traits::image_cache::ImageCache;
 use profile_traits::mem::ReportsChan;
 use rpc::LayoutRPC;
 use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
 use script_traits::{ScrollState, UntrustedNodeAddress, WindowSizeData};
--- a/servo/components/script_layout_interface/rpc.rs
+++ b/servo/components/script_layout_interface/rpc.rs
@@ -1,15 +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 http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
+use euclid::{Point2D, Rect};
 use script_traits::UntrustedNodeAddress;
 use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left, overflow_x};
 use webrender_traits::ClipId;
 
 /// Synchronous messages that script can send to layout.
 ///
 /// In general, you should use messages to talk to Layout. Use the RPC interface
 /// if and only if the work is
--- a/servo/components/script_traits/Cargo.toml
+++ b/servo/components/script_traits/Cargo.toml
@@ -10,27 +10,27 @@ name = "script_traits"
 path = "lib.rs"
 
 [dependencies]
 app_units = "0.4"
 bluetooth_traits = {path = "../bluetooth_traits"}
 canvas_traits = {path = "../canvas_traits"}
 cookie = "0.6"
 devtools_traits = {path = "../devtools_traits"}
-euclid = "0.13"
+euclid = "0.14.4"
 gfx_traits = {path = "../gfx_traits"}
 heapsize = "0.4"
 heapsize_derive = "0.1"
 hyper = "0.10"
 hyper_serde = "0.6"
 ipc-channel = "0.7"
 libc = "0.2"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
-offscreen_gl_context = "0.8"
+offscreen_gl_context = { version = "0.9", features = ["serde"] }
 profile_traits = {path = "../profile_traits"}
 rustc-serialize = "0.3.4"
 serde = "0.9"
 serde_derive = "0.9"
 servo_atoms = {path = "../atoms"}
 servo_url = {path = "../url"}
 style_traits = {path = "../style_traits", features = ["servo"]}
 time = "0.1.12"
--- a/servo/components/script_traits/lib.rs
+++ b/servo/components/script_traits/lib.rs
@@ -39,22 +39,17 @@ extern crate webrender_traits;
 extern crate webvr_traits;
 
 mod script_msg;
 pub mod webdriver_msg;
 
 use app_units::Au;
 use bluetooth_traits::BluetoothRequest;
 use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
-use euclid::Size2D;
-use euclid::length::Length;
-use euclid::point::Point2D;
-use euclid::rect::Rect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::TypedSize2D;
+use euclid::{Size2D, Length, Point2D, Vector2D, Rect, ScaleFactor, TypedSize2D};
 use gfx_traits::Epoch;
 use heapsize::HeapSizeOf;
 use hyper::header::Headers;
 use hyper::method::Method;
 use ipc_channel::ipc::{IpcReceiver, IpcSender};
 use libc::c_void;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, Key, KeyModifiers, KeyState};
 use msg::constellation_msg::{PipelineId, PipelineNamespaceId, TraversalDirection};
@@ -249,17 +244,17 @@ pub enum ConstellationControlMsg {
     ExitPipeline(PipelineId, DiscardBrowsingContext),
     /// Notifies the script that the whole thread should be closed.
     ExitScriptThread,
     /// Sends a DOM event.
     SendEvent(PipelineId, CompositorEvent),
     /// Notifies script of the viewport.
     Viewport(PipelineId, Rect<f32>),
     /// Notifies script of a new set of scroll offsets.
-    SetScrollState(PipelineId, Vec<(UntrustedNodeAddress, Point2D<f32>)>),
+    SetScrollState(PipelineId, Vec<(UntrustedNodeAddress, Vector2D<f32>)>),
     /// Requests that the script thread immediately send the constellation the title of a pipeline.
     GetTitle(PipelineId),
     /// Notifies script thread of a change to one of its document's activity
     SetDocumentActivity(PipelineId, DocumentActivity),
     /// Notifies script thread whether frame is visible
     ChangeFrameVisibilityStatus(PipelineId, bool),
     /// Notifies script thread that frame visibility change is complete
     /// PipelineId is for the parent, BrowsingContextId is for the nested browsing context
@@ -685,17 +680,17 @@ pub enum AnimationTickType {
 }
 
 /// The scroll state of a stacking context.
 #[derive(Copy, Clone, Debug, Deserialize, Serialize)]
 pub struct ScrollState {
     /// The ID of the scroll root.
     pub scroll_root_id: ClipId,
     /// The scrolling offset of this stacking context.
-    pub scroll_offset: Point2D<f32>,
+    pub scroll_offset: Vector2D<f32>,
 }
 
 /// One hardware pixel.
 ///
 /// This unit corresponds to the smallest addressable element of the display hardware.
 #[derive(Copy, Clone, Debug)]
 pub enum DevicePixel {}
 
--- a/servo/components/script_traits/script_msg.rs
+++ b/servo/components/script_traits/script_msg.rs
@@ -9,18 +9,17 @@ use IFrameLoadInfo;
 use IFrameLoadInfoWithData;
 use LayoutControlMsg;
 use LoadData;
 use MozBrowserEvent;
 use WorkerGlobalScopeInit;
 use WorkerScriptLoadOrigin;
 use canvas_traits::CanvasMsg;
 use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
-use euclid::point::Point2D;
-use euclid::size::{Size2D, TypedSize2D};
+use euclid::{Point2D, Size2D, TypedSize2D};
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::{BrowsingContextId, TopLevelBrowsingContextId, FrameType, PipelineId, TraversalDirection};
 use msg::constellation_msg::{Key, KeyModifiers, KeyState};
 use net_traits::CoreResourceMsg;
 use net_traits::request::RequestInit;
 use net_traits::storage_thread::StorageType;
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
 use servo_url::ImmutableOrigin;
--- a/servo/components/script_traits/webdriver_msg.rs
+++ b/servo/components/script_traits/webdriver_msg.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/. */
 
 #![allow(missing_docs)]
 
 use cookie_rs::Cookie;
-use euclid::rect::Rect;
+use euclid::Rect;
 use hyper_serde::Serde;
 use ipc_channel::ipc::IpcSender;
 use msg::constellation_msg::BrowsingContextId;
 use rustc_serialize::json::{Json, ToJson};
 use servo_url::ServoUrl;
 
 #[derive(Deserialize, Serialize)]
 pub enum WebDriverScriptCommand {
--- a/servo/components/servo/Cargo.toml
+++ b/servo/components/servo/Cargo.toml
@@ -25,17 +25,17 @@ bluetooth = {path = "../bluetooth"}
 canvas = {path = "../canvas"}
 canvas_traits = {path = "../canvas_traits"}
 compositing = {path = "../compositing"}
 constellation = {path = "../constellation"}
 debugger = {path = "../debugger"}
 devtools = {path = "../devtools"}
 devtools_traits = {path = "../devtools_traits"}
 env_logger = "0.4"
-euclid = "0.13"
+euclid = "0.14.4"
 gfx = {path = "../gfx"}
 gleam = "0.4"
 ipc-channel = "0.7"
 layout_thread = {path = "../layout_thread"}
 log = "0.3"
 msg = {path = "../msg"}
 net = {path = "../net"}
 net_traits = {path = "../net_traits"}
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -35,17 +35,17 @@ arrayvec = "0.3.20"
 arraydeque = "0.2.3"
 atomic_refcell = "0.1"
 bitflags = "0.7"
 bit-vec = "0.4.3"
 byteorder = "1.0"
 cfg-if = "0.1.0"
 cssparser = "0.14.0"
 encoding = {version = "0.2", optional = true}
-euclid = "0.13"
+euclid = "0.14.4"
 fnv = "1.0"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 itoa = "0.3"
 html5ever = {version = "0.17", optional = true}
 lazy_static = "0.2"
 log = "0.3"
 matches = "0.1"
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -4,17 +4,17 @@
 
 //! CSS transitions and animations.
 #![deny(missing_docs)]
 
 use Atom;
 use bezier::Bezier;
 use context::SharedStyleContext;
 use dom::OpaqueNode;
-use euclid::point::Point2D;
+use euclid::Point2D;
 use font_metrics::FontMetricsProvider;
 use properties::{self, CascadeFlags, ComputedValues, Importance};
 use properties::animated_properties::{AnimatedProperty, TransitionProperty};
 use properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
 use properties::longhands::animation_iteration_count::single_value::computed_value::T as AnimationIterationCount;
 use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
 use rule_tree::CascadeLevel;
 use std::sync::mpsc::Sender;
--- a/servo/components/style/bezier.rs
+++ b/servo/components/style/bezier.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Parametric Bézier curves.
 //!
 //! This is based on `WebCore/platform/graphics/UnitBezier.h` in WebKit.
 
 #![deny(missing_docs)]
 
-use euclid::point::Point2D;
+use euclid::Point2D;
 
 const NEWTON_METHOD_ITERATIONS: u8 = 8;
 
 /// A unit cubic Bézier curve, used for timing functions in CSS transitions and animations.
 pub struct Bezier {
     ax: f64,
     bx: f64,
     cx: f64,
--- a/servo/components/style/gecko_bindings/sugar/ns_timing_function.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_timing_function.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::point::{Point2D, TypedPoint2D};
+use euclid::{Point2D, TypedPoint2D};
 use gecko_bindings::structs::{nsTimingFunction, nsTimingFunction_Type};
 use std::mem;
 use values::computed::ToComputedValue;
 use values::computed::transform::TimingFunction as ComputedTimingFunction;
 use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, TimingKeyword};
 use values::specified::transform::TimingFunction;
 
 impl nsTimingFunction {
--- a/servo/components/style/logical_geometry.rs
+++ b/servo/components/style/logical_geometry.rs
@@ -1,17 +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/. */
 
 //! Geometry in flow-relative space.
 
-use euclid::{Point2D, Rect, Size2D};
+use euclid::{Point2D, Rect, Size2D, SideOffsets2D};
 use euclid::num::Zero;
-use euclid::side_offsets::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/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -17,17 +17,17 @@ use std::mem;
 use std::ops::Deref;
 use stylearc::{Arc, UniqueArc};
 
 use app_units::Au;
 #[cfg(feature = "servo")] use cssparser::RGBA;
 use cssparser::{Parser, TokenSerializationType, serialize_identifier};
 use cssparser::ParserInput;
 use error_reporting::ParseErrorReporter;
-#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
+#[cfg(feature = "servo")] use euclid::SideOffsets2D;
 use computed_values;
 use context::QuirksMode;
 use font_metrics::FontMetricsProvider;
 #[cfg(feature = "gecko")] use gecko_bindings::bindings;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID};
 #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
 use logical_geometry::WritingMode;
 use media_queries::Device;
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -7,17 +7,17 @@
 //! [at]: https://drafts.csswg.org/css-device-adapt/#atviewport-rule
 //! [meta]: https://drafts.csswg.org/css-device-adapt/#viewport-meta
 
 use app_units::Au;
 use context::QuirksMode;
 use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
 use cssparser::ToCss as ParserToCss;
 use error_reporting::ContextualParseError;
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use font_metrics::get_metrics_provider_for_product;
 use media_queries::Device;
 use parser::{Parse, ParserContext, log_css_error};
 use properties::StyleBuilder;
 use selectors::parser::SelectorParseError;
 use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
 use std::ascii::AsciiExt;
 use std::borrow::Cow;
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.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/. */
 
 //! Computed values.
 
 use Atom;
 use context::QuirksMode;
-use euclid::size::Size2D;
+use euclid::Size2D;
 use font_metrics::FontMetricsProvider;
 use media_queries::Device;
 use num_traits::Zero;
 #[cfg(feature = "gecko")]
 use properties;
 use properties::{ComputedValues, StyleBuilder};
 use std::f32;
 use std::f32::consts::PI;
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! [Length values][length].
 //!
 //! [length]: https://drafts.csswg.org/css-values/#lengths
 
 use app_units::Au;
 use cssparser::{Parser, Token, BasicParseError};
-use euclid::size::Size2D;
+use euclid::Size2D;
 use font_metrics::FontMetricsQueryResult;
 use parser::{Parse, ParserContext};
 use std::{cmp, fmt, mem};
 use std::ascii::AsciiExt;
 use std::ops::Mul;
 use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
 use style_traits::values::specified::{AllowedLengthType, AllowedNumericType};
 use stylesheets::CssRuleType;
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -13,14 +13,14 @@ path = "lib.rs"
 servo = ["heapsize", "heapsize_derive", "serde", "serde_derive",
          "cssparser/heapsize", "cssparser/serde"]
 gecko = []
 
 [dependencies]
 app_units = "0.4.1"
 bitflags = "0.7"
 cssparser = "0.14.0"
-euclid = "0.13"
+euclid = "0.14.4"
 heapsize = {version = "0.4", optional = true}
 heapsize_derive = {version = "0.1", optional = true}
 selectors = { path = "../selectors" }
 serde = {version = "0.9", optional = true}
 serde_derive = {version = "0.9", optional = true}
--- 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 http://mozilla.org/MPL/2.0/. */
 
 //! Helper types for the `@viewport` rule.
 
 use {CSSPixel, PinchZoomFactor, ParseError};
 use cssparser::{Parser, ToCss, ParseError as CssParseError, BasicParseError};
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use std::ascii::AsciiExt;
 use std::fmt;
 
 define_css_keyword_enum!(UserZoom:
                          "zoom" => Zoom,
                          "fixed" => Fixed);
 
 define_css_keyword_enum!(Orientation:
--- a/servo/components/webdriver_server/Cargo.toml
+++ b/servo/components/webdriver_server/Cargo.toml
@@ -7,17 +7,17 @@ publish = false
 
 [lib]
 name = "webdriver_server"
 path = "lib.rs"
 
 [dependencies]
 base64 = "0.5.2"
 cookie = "0.6"
-euclid = "0.13"
+euclid = "0.14"
 hyper = "0.10"
 image = "0.12"
 ipc-channel = "0.7"
 log = "0.3.5"
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 regex = "0.2"
 rustc-serialize = "0.3.4"
--- a/servo/ports/cef/Cargo.toml
+++ b/servo/ports/cef/Cargo.toml
@@ -15,17 +15,17 @@ opt-level = 3
 # lto = false
 
 [features]
 debugmozjs = ["libservo/debugmozjs"]
 
 [dependencies]
 compositing = {path = "../../components/compositing"}
 devtools = {path = "../../components/devtools"}
-euclid = "0.13"
+euclid = "0.14.4"
 gleam = "0.4"
 glutin_app = {path = "../glutin"}
 libc = "0.2"
 libservo = {path = "../../components/servo"}
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 msg = {path = "../../components/msg"}
 net_traits = {path = "../../components/net_traits"}
 script_traits = {path = "../../components/script_traits"}
--- a/servo/ports/cef/browser_host.rs
+++ b/servo/ports/cef/browser_host.rs
@@ -7,18 +7,17 @@ use eutil::Downcast;
 use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_t, cef_browser_host_t, cef_client_t};
 use types::cef_event_flags_t::{EVENTFLAG_ALT_DOWN, EVENTFLAG_CONTROL_DOWN, EVENTFLAG_SHIFT_DOWN};
 use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN};
 use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event, cef_window_handle_t};
 use webrender_traits::ScrollLocation;
 use wrappers::CefWrap;
 
 use compositing::windowing::{WindowEvent, MouseWindowEvent};
-use euclid::point::TypedPoint2D;
-use euclid::size::TypedSize2D;
+use euclid::{TypedPoint2D, TypedVector2D, TypedSize2D};
 use libc::{c_double, c_int};
 use msg::constellation_msg::{self, KeyModifiers, KeyState};
 use script_traits::{MouseButton, TouchEventType};
 use std::cell::{Cell, RefCell};
 use std::char;
 
 pub struct ServoCefBrowserHost {
     /// A reference to the browser.
@@ -465,17 +464,17 @@ full_cef_class_impl! {
         fn send_mouse_wheel_event(&this,
                                   event: *const cef_mouse_event [&cef_mouse_event],
                                   delta_x: c_int [c_int],
                                   delta_y: c_int [c_int],)
                                   -> () {{
             let event: &cef_mouse_event = event;
             let delta_x: c_int = delta_x;
             let delta_y: c_int = delta_y;
-            let delta = TypedPoint2D::new(delta_x as f32, delta_y as f32);
+            let delta = TypedVector2D::new(delta_x as f32, delta_y as f32);
             let origin = TypedPoint2D::new((*event).x as i32, (*event).y as i32);
             this.downcast().send_window_event(WindowEvent::Scroll(ScrollLocation::Delta(delta),
                                                                   origin,
                                                                   TouchEventType::Move))
         }}
 
         fn get_zoom_level(&this,) -> c_double {{
             this.downcast().pinch_zoom_level() as c_double
--- a/servo/ports/cef/window.rs
+++ b/servo/ports/cef/window.rs
@@ -14,20 +14,17 @@ use eutil::Downcast;
 use interfaces::CefApp;
 use interfaces::CefBrowser;
 use render_handler::CefRenderHandlerExtensions;
 use types::{cef_cursor_handle_t, cef_cursor_type_t, cef_rect_t};
 use wrappers::CefWrap;
 
 use compositing::compositor_thread::EventLoopWaker;
 use compositing::windowing::{WindowEvent, WindowMethods};
-use euclid::point::{Point2D, TypedPoint2D};
-use euclid::rect::TypedRect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::{Size2D, TypedSize2D};
+use euclid::{Point2D, TypedPoint2D, TypedRect, Size2D, TypedSize2D, ScaleFactor};
 use gleam::gl;
 use msg::constellation_msg::{Key, KeyModifiers};
 use net_traits::net_error_list::NetError;
 use script_traits::{DevicePixel, LoadData};
 use servo_geometry::DeviceIndependentPixel;
 use std::cell::RefCell;
 use std::ffi::CString;
 use std::os::raw::{c_char, c_void};
--- a/servo/ports/glutin/Cargo.toml
+++ b/servo/ports/glutin/Cargo.toml
@@ -6,17 +6,17 @@ license = "MPL-2.0"
 
 [lib]
 name = "glutin_app"
 path = "lib.rs"
 
 [dependencies]
 bitflags = "0.7"
 compositing = {path = "../../components/compositing"}
-euclid = "0.13"
+euclid = "0.14.4"
 gleam = "0.4"
 log = "0.3.5"
 msg = {path = "../../components/msg"}
 net_traits = {path = "../../components/net_traits"}
 script_traits = {path = "../../components/script_traits"}
 servo-glutin = "0.10"
 servo_geometry = {path = "../../components/geometry"}
 servo_config = {path = "../../components/config"}
--- a/servo/ports/glutin/window.rs
+++ b/servo/ports/glutin/window.rs
@@ -3,20 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! A windowing implementation using glutin.
 
 use NestedEventLoopListener;
 use compositing::compositor_thread::EventLoopWaker;
 use compositing::windowing::{MouseWindowEvent, WindowNavigateMsg};
 use compositing::windowing::{WindowEvent, WindowMethods};
-use euclid::{Point2D, Size2D, TypedPoint2D};
-use euclid::rect::TypedRect;
-use euclid::scale_factor::ScaleFactor;
-use euclid::size::TypedSize2D;
+use euclid::{Point2D, Size2D, TypedPoint2D, TypedVector2D, TypedRect, ScaleFactor, TypedSize2D};
 #[cfg(target_os = "windows")]
 use gdi32;
 use gleam::gl;
 use glutin;
 use glutin::{Api, ElementState, Event, GlRequest, MouseButton, MouseScrollDelta, VirtualKeyCode};
 #[cfg(not(target_os = "windows"))]
 use glutin::ScanCode;
 use glutin::TouchPhase;
@@ -496,17 +493,17 @@ impl Window {
                 self.event_queue.borrow_mut().push(
                     WindowEvent::MouseWindowMoveEventClass(TypedPoint2D::new(x as f32, y as f32)));
             }
             Event::MouseWheel(delta, phase, pos) => {
                 let (dx, dy) = match delta {
                     MouseScrollDelta::LineDelta(dx, dy) => (dx, dy * LINE_HEIGHT),
                     MouseScrollDelta::PixelDelta(dx, dy) => (dx, dy),
                 };
-                let scroll_location = ScrollLocation::Delta(TypedPoint2D::new(dx, dy));
+                let scroll_location = ScrollLocation::Delta(TypedVector2D::new(dx, dy));
                 if let Some((x, y)) = pos {
                     self.mouse_pos.set(Point2D::new(x, y));
                     self.event_queue.borrow_mut().push(
                         WindowEvent::MouseWindowMoveEventClass(TypedPoint2D::new(x as f32, y as f32)));
                 };
                 let phase = glutin_phase_to_touch_event_type(phase);
                 self.scroll_window(scroll_location, phase);
             },
@@ -1227,26 +1224,26 @@ impl WindowMethods for Window {
             (CMD_OR_ALT, None, Key::Right) => {
                 self.event_queue.borrow_mut().push(WindowEvent::Navigation(WindowNavigateMsg::Forward));
             }
             (CMD_OR_ALT, None, Key::Left) => {
                 self.event_queue.borrow_mut().push(WindowEvent::Navigation(WindowNavigateMsg::Back));
             }
 
             (NONE, None, Key::PageDown) => {
-               let scroll_location = ScrollLocation::Delta(TypedPoint2D::new(0.0,
+               let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                    -self.framebuffer_size()
                                         .to_f32()
                                         .to_untyped()
                                         .height + 2.0 * LINE_HEIGHT));
                 self.scroll_window(scroll_location,
                                    TouchEventType::Move);
             }
             (NONE, None, Key::PageUp) => {
-                let scroll_location = ScrollLocation::Delta(TypedPoint2D::new(0.0,
+                let scroll_location = ScrollLocation::Delta(TypedVector2D::new(0.0,
                                    self.framebuffer_size()
                                        .to_f32()
                                        .to_untyped()
                                        .height - 2.0 * LINE_HEIGHT));
                 self.scroll_window(scroll_location,
                                    TouchEventType::Move);
             }
 
@@ -1254,28 +1251,28 @@ impl WindowMethods for Window {
                 self.scroll_window(ScrollLocation::Start, TouchEventType::Move);
             }
 
             (NONE, None, Key::End) => {
                 self.scroll_window(ScrollLocation::End, TouchEventType::Move);
             }
 
             (NONE, None, Key::Up) => {
-                self.scroll_window(ScrollLocation::Delta(TypedPoint2D::new(0.0, 3.0 * LINE_HEIGHT)),
+                self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(0.0, 3.0 * LINE_HEIGHT)),
                                    TouchEventType::Move);
             }
             (NONE, None, Key::Down) => {
-                self.scroll_window(ScrollLocation::Delta(TypedPoint2D::new(0.0, -3.0 * LINE_HEIGHT)),
+                self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(0.0, -3.0 * LINE_HEIGHT)),
                                    TouchEventType::Move);
             }
             (NONE, None, Key::Left) => {
-                self.scroll_window(ScrollLocation::Delta(TypedPoint2D::new(LINE_HEIGHT, 0.0)), TouchEventType::Move);
+                self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(LINE_HEIGHT, 0.0)), TouchEventType::Move);
             }
             (NONE, None, Key::Right) => {
-                self.scroll_window(ScrollLocation::Delta(TypedPoint2D::new(-LINE_HEIGHT, 0.0)), TouchEventType::Move);
+                self.scroll_window(ScrollLocation::Delta(TypedVector2D::new(-LINE_HEIGHT, 0.0)), TouchEventType::Move);
             }
             (CMD_OR_CONTROL, Some('r'), _) => {
                 if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
                     self.event_queue.borrow_mut().push(WindowEvent::Reload);
                 }
             }
             (CMD_OR_CONTROL, Some('q'), _) => {
                 if let Some(true) = PREFS.get("shell.builtin-key-shortcuts.enabled").as_boolean() {
--- a/servo/python/tidy/servo_tidy_tests/rust_tidy.rs
+++ b/servo/python/tidy/servo_tidy_tests/rust_tidy.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    app_units::Au;
 use azure::azure_hl::{ AntialiasMode, Color, ColorPattern, CompositionOp };
 use azure::azure_hl::{AntialiasMode, Color,
 ColorPattern, CompositionOp};
-use euclid::size::Size2D;
+use euclid::Size2D;
 use azure::azure::AzIntSize;
 use azure::azure::{AzIntSize};
 
 use std;
 
 mod paint_context;
 pub mod display_list;
 mod test::{
--- a/servo/tests/unit/script/Cargo.toml
+++ b/servo/tests/unit/script/Cargo.toml
@@ -5,12 +5,12 @@ authors = ["The Servo Project Developers
 license = "MPL-2.0"
 
 [lib]
 name = "script_tests"
 path = "lib.rs"
 doctest = false
 
 [dependencies]
-euclid = "0.13"
+euclid = "0.14.4"
 msg = {path = "../../../components/msg"}
 script = {path = "../../../components/script"}
 servo_url = {path = "../../../components/url"}
--- a/servo/tests/unit/script/htmlareaelement.rs
+++ b/servo/tests/unit/script/htmlareaelement.rs
@@ -2,17 +2,17 @@
 // 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 euclid::point::Point2D;
+use euclid::Point2D;
 use script::test::area::{Area, Shape};
 
 #[test]
 fn garbage_input() {
     assert!(Area::parse(";.,()8.2", Shape::Circle).is_none())
 }
 
 #[test]
--- a/servo/tests/unit/style/Cargo.toml
+++ b/servo/tests/unit/style/Cargo.toml
@@ -11,17 +11,17 @@ doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 byteorder = "1.0"
 app_units = "0.4.1"
 cssparser = "0.14.0"
-euclid = "0.13"
+euclid = "0.14.4"
 html5ever = "0.17"
 parking_lot = "0.3"
 rayon = "0.7"
 rustc-serialize = "0.3"
 selectors = {path = "../../../components/selectors"}
 servo_atoms = {path = "../../../components/atoms"}
 servo_config = {path = "../../../components/config"}
 servo_url = {path = "../../../components/url"}
--- 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 http://mozilla.org/MPL/2.0/. */
 
 use cssparser::{Parser, SourcePosition};
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use servo_url::ServoUrl;
 use std::borrow::ToOwned;
 use style::Atom;
 use style::context::QuirksMode;
 use style::error_reporting::{ParseErrorReporter, ContextualParseError};
 use style::media_queries::*;
 use style::servo::media_queries::*;
 use style::shared_lock::SharedRwLock;
--- a/servo/tests/unit/style/parsing/mod.rs
+++ b/servo/tests/unit/style/parsing/mod.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/. */
 
 //! Tests for parsing and serialization of values/properties
 
 use cssparser::{Parser, ParserInput};
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use media_queries::CSSErrorReporterTest;
 use style::context::QuirksMode;
 use style::font_metrics::ServoMetricsProvider;
 use style::media_queries::{Device, MediaType};
 use style::parser::ParserContext;
 use style::properties::{ComputedValues, StyleBuilder};
 use style::stylesheets::{CssRuleType, Origin};
 use style::values::computed::{Context, ToComputedValue};
--- a/servo/tests/unit/style/viewport.rs
+++ b/servo/tests/unit/style/viewport.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 http://mozilla.org/MPL/2.0/. */
 
 use cssparser::{Parser, ParserInput};
-use euclid::size::TypedSize2D;
+use euclid::TypedSize2D;
 use media_queries::CSSErrorReporterTest;
 use servo_config::prefs::{PREFS, PrefValue};
 use servo_url::ServoUrl;
 use style::context::QuirksMode;
 use style::media_queries::{Device, MediaList, MediaType};
 use style::parser::{Parse, ParserContext};
 use style::shared_lock::SharedRwLock;
 use style::stylearc::Arc;
--- a/servo/tests/unit/stylo/Cargo.toml
+++ b/servo/tests/unit/stylo/Cargo.toml
@@ -13,16 +13,16 @@ doctest = false
 
 [features]
 testing = ["style/testing"]
 
 [dependencies]
 atomic_refcell = "0.1"
 cssparser = "0.14.0"
 env_logger = "0.4"
-euclid = "0.13"
+euclid = "0.14.4"
 geckoservo = {path = "../../../ports/geckolib"}
 libc = "0.2"
 log = {version = "0.3.5", features = ["release_max_level_info"]}
 selectors = {path = "../../../components/selectors", features = ["gecko_like_types"]}
 size_of_test = {path = "../../../components/size_of_test"}
 style_traits = {path = "../../../components/style_traits"}
 style = {path = "../../../components/style", features = ["gecko"]}