From 4e530d2f5f625ec78ab0246ad797b788c2abee8a Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Fri, 20 Jul 2018 17:24:55 -0400 Subject: [PATCH] Bug 1476636. Update Cargo lockfiles, re-vendor rust dependencies --HG-- rename : third_party/rust/euclid-0.17.3/LICENSE-APACHE => third_party/rust/smallvec/LICENSE-APACHE --- Cargo.lock | 58 +- .../rust/euclid-0.17.3/.cargo-checksum.json | 1 - third_party/rust/euclid-0.17.3/.travis.yml | 25 - third_party/rust/euclid-0.17.3/COPYRIGHT | 5 - third_party/rust/euclid-0.17.3/Cargo.toml | 38 - third_party/rust/euclid-0.17.3/README.md | 8 - .../rust/euclid-0.17.3/src/approxeq.rs | 35 - third_party/rust/euclid-0.17.3/src/homogen.rs | 109 -- third_party/rust/euclid-0.17.3/src/length.rs | 515 ------ third_party/rust/euclid-0.17.3/src/lib.rs | 126 -- third_party/rust/euclid-0.17.3/src/macros.rs | 81 - third_party/rust/euclid-0.17.3/src/num.rs | 85 - third_party/rust/euclid-0.17.3/src/point.rs | 899 ----------- third_party/rust/euclid-0.17.3/src/rect.rs | 805 ---------- .../rust/euclid-0.17.3/src/rotation.rs | 1057 ------------ third_party/rust/euclid-0.17.3/src/scale.rs | 230 --- .../rust/euclid-0.17.3/src/side_offsets.rs | 138 -- third_party/rust/euclid-0.17.3/src/size.rs | 373 ----- .../rust/euclid-0.17.3/src/transform2d.rs | 525 ------ .../rust/euclid-0.17.3/src/transform3d.rs | 990 ------------ third_party/rust/euclid-0.17.3/src/trig.rs | 69 - third_party/rust/euclid-0.17.3/src/vector.rs | 1417 ----------------- third_party/rust/gleam/.cargo-checksum.json | 2 +- third_party/rust/gleam/Cargo.toml | 2 +- third_party/rust/gleam/build.rs | 21 +- third_party/rust/gleam/src/gl.rs | 35 +- third_party/rust/gleam/src/gl_fns.rs | 37 +- third_party/rust/gleam/src/gles_fns.rs | 37 +- .../rust/plane-split/.cargo-checksum.json | 2 +- third_party/rust/plane-split/Cargo.toml | 4 +- third_party/rust/plane-split/src/polygon.rs | 12 +- third_party/rust/plane-split/tests/main.rs | 2 +- third_party/rust/plane-split/tests/split.rs | 14 +- .../rust/smallvec/.cargo-checksum.json | 2 +- third_party/rust/smallvec/.travis.yml | 5 +- third_party/rust/smallvec/Cargo.toml | 10 +- third_party/rust/smallvec/LICENSE | 374 ----- .../LICENSE-APACHE | 0 .../{euclid-0.17.3 => smallvec}/LICENSE-MIT | 2 +- third_party/rust/smallvec/benches/bench.rs | 283 +++- third_party/rust/smallvec/lib.rs | 664 ++++++-- 41 files changed, 795 insertions(+), 8302 deletions(-) delete mode 100644 third_party/rust/euclid-0.17.3/.cargo-checksum.json delete mode 100644 third_party/rust/euclid-0.17.3/.travis.yml delete mode 100644 third_party/rust/euclid-0.17.3/COPYRIGHT delete mode 100644 third_party/rust/euclid-0.17.3/Cargo.toml delete mode 100644 third_party/rust/euclid-0.17.3/README.md delete mode 100644 third_party/rust/euclid-0.17.3/src/approxeq.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/homogen.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/length.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/lib.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/macros.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/num.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/point.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/rect.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/rotation.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/scale.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/side_offsets.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/size.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/transform2d.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/transform3d.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/trig.rs delete mode 100644 third_party/rust/euclid-0.17.3/src/vector.rs delete mode 100644 third_party/rust/smallvec/LICENSE rename third_party/rust/{euclid-0.17.3 => smallvec}/LICENSE-APACHE (100%) rename third_party/rust/{euclid-0.17.3 => smallvec}/LICENSE-MIT (95%) diff --git a/Cargo.lock b/Cargo.lock index ef14f2b650ee..f7b432eaa35f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,7 +437,7 @@ dependencies = [ "proc-macro2 0.4.6 (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.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -661,27 +661,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "euclid" -version = "0.17.3" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "euclid" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fallible" version = "0.0.1" dependencies = [ "hashglobe 0.1.0", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -811,7 +803,7 @@ dependencies = [ "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.19.0", "servo_arc 0.1.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", ] @@ -873,7 +865,7 @@ dependencies = [ [[package]] name = "gleam" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1145,7 +1137,7 @@ dependencies = [ "selectors 0.19.0", "servo_arc 0.1.1", "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1502,7 +1494,7 @@ dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1566,11 +1558,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "plane-split" -version = "0.9.1" +version = "0.10.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.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1814,7 +1806,7 @@ dependencies = [ "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "servo_arc 0.1.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1890,8 +1882,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "stable_deref_trait" @@ -1976,7 +1971,7 @@ dependencies = [ "selectors 0.19.0", "servo_arc 0.1.1", "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "style_derive 0.0.1", "style_traits 0.0.1", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2028,7 +2023,7 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.19.0", "size_of_test 0.0.1", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", ] @@ -2354,18 +2349,18 @@ dependencies = [ "core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 10.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", - "plane-split 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "plane-split 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "webrender_api 0.57.2", @@ -2382,7 +2377,7 @@ dependencies = [ "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)", @@ -2398,10 +2393,10 @@ dependencies = [ "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "nsstring 0.1.0", "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2596,7 +2591,6 @@ dependencies = [ "checksum encoding_rs 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88a1b66a0d28af4b03a8c8278c6dcb90e6e600d89c14500a9e7a02e64b9ee3ac" "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c95fd0d455f114291a3109286bd387bd423770058474a2d3f38b712cd661df60" "checksum euclid 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47d5eb6310c8dd3e79f973952ddcb180bf6a98c01d341add49126a094b5598cc" "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" @@ -2612,7 +2606,7 @@ dependencies = [ "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" -"checksum gleam 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e47b39459e47b76be4d2c82702932cdc66df09dcb8f813424167991adb8b3380" +"checksum gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d41e7ac812597988fdae31c9baec3c6d35cadb8ad9ab88a9bf9c0f119ed66c2" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" @@ -2678,7 +2672,7 @@ dependencies = [ "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.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7079b8485b4f9d9560dee7a69ca8f6ca781f9f284ff9d2bf27255d440b03e4af" +"checksum plane-split 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e14382aabad89085fbf714f75d527492bb672725facb9b2ced2fada47cf418c" "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" @@ -2715,7 +2709,7 @@ dependencies = [ "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c" -"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" +"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7" diff --git a/third_party/rust/euclid-0.17.3/.cargo-checksum.json b/third_party/rust/euclid-0.17.3/.cargo-checksum.json deleted file mode 100644 index 8e200af23b96..000000000000 --- a/third_party/rust/euclid-0.17.3/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{".travis.yml":"301590735ff27f124c03cef8598aa5397c88c59aba3d058edf0bde532965c346","COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"2d7ade90b1883e9ec1e718b52a7c1785adf7d8f482a3d2a2813079ad15de906b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/homogen.rs":"df6bdb87aee7422c19cf8ce633c70656ebea789b96f6fcc396baecc4c3ef6ab3","src/length.rs":"5c0784bccb1840f1bc86f45c80094584ca2f60b6a644797a5e760341c15c6e50","src/lib.rs":"ef31060a582a8a133750aeaa7244cc6bbb709a0aec7d964a76b54643bb9f7134","src/macros.rs":"ccb9aeb942f571ec4207334b87c87f59a9a4d666039d143d7673372679c42347","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"50ccf38962b2aee2b0b2e7c516f24e54908286953cb7cf97b5a6b9fb7bdfc91b","src/rect.rs":"b96f267123972d7d924d08d8b93bea9333d71654febe20063c532a11f7c7ae30","src/rotation.rs":"2686d8624671f48e9c657a98c9ac3345f3c4028e65ee3ef588d407ffd020fb86","src/scale.rs":"80c96c99cc916cac155fc898cd34a771a64ab46a60340cb7de876d224f0c7cb1","src/side_offsets.rs":"604e104616777515e0e0e68262110c55fe9c0ce4deeb6d022e5b4984df11e29f","src/size.rs":"ee722964a6e6654eacd8f321f5c3f62452237316d9d2dac8a98753f6227c4fce","src/transform2d.rs":"edf9b82411a25d8f6b2a867a5b579c15316b3fd112eb463f6589012039670be3","src/transform3d.rs":"797c445c99edace0a6e51e166cdbeb667620c6fd98cbc0249742bbd09588dc7f","src/trig.rs":"78b8fb26d2fded11c4b8aa47935e80c474696aee1999c688642534b667e005d9","src/vector.rs":"37215522068612107acca427c83159f4bca79ae41a2f54d9c7d0feb4b28b2348"},"package":"c95fd0d455f114291a3109286bd387bd423770058474a2d3f38b712cd661df60"} \ No newline at end of file diff --git a/third_party/rust/euclid-0.17.3/.travis.yml b/third_party/rust/euclid-0.17.3/.travis.yml deleted file mode 100644 index 90605ea0cdee..000000000000 --- a/third_party/rust/euclid-0.17.3/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: rust - -notifications: - webhooks: http://build.servo.org:54856/travis - -rust: - - 1.23.0 - - stable - - beta - - nightly - -env: - - FEATURES="" - - FEATURES="--features serde" - -matrix: - include: - - rust: nightly - env: FEATURES="--features unstable" - - rust: nightly - env: FEATURES="--features unstable,serde" - -script: - - cargo build $FEATURES - - cargo test --verbose $FEATURES diff --git a/third_party/rust/euclid-0.17.3/COPYRIGHT b/third_party/rust/euclid-0.17.3/COPYRIGHT deleted file mode 100644 index 8b7291ad281c..000000000000 --- a/third_party/rust/euclid-0.17.3/COPYRIGHT +++ /dev/null @@ -1,5 +0,0 @@ -Licensed under the Apache License, Version 2.0 or the MIT license -, at your -option. All files in the project carrying such notice may not be -copied, modified, or distributed except according to those terms. diff --git a/third_party/rust/euclid-0.17.3/Cargo.toml b/third_party/rust/euclid-0.17.3/Cargo.toml deleted file mode 100644 index 41c88a5cedab..000000000000 --- a/third_party/rust/euclid-0.17.3/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g. crates.io) dependencies -# -# If you believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -name = "euclid" -version = "0.17.3" -authors = ["The Servo Project Developers"] -description = "Geometry primitives" -documentation = "https://docs.rs/euclid/" -keywords = ["matrix", "vector", "linear-algebra", "geometry"] -categories = ["science"] -license = "MIT / Apache-2.0" -repository = "https://github.com/servo/euclid" -[dependencies.num-traits] -version = "0.1.32" -default-features = false - -[dependencies.serde] -version = "1.0" -features = ["serde_derive"] -optional = true -[dev-dependencies.rand] -version = "0.4" - -[dev-dependencies.serde_test] -version = "1.0" - -[features] -unstable = [] diff --git a/third_party/rust/euclid-0.17.3/README.md b/third_party/rust/euclid-0.17.3/README.md deleted file mode 100644 index 13b488da9f69..000000000000 --- a/third_party/rust/euclid-0.17.3/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# euclid - -This is a small library for geometric types with a focus on 2d graphics and -layout. - -* [Documentation](https://docs.rs/euclid/) -* [Release notes](https://github.com/servo/euclid/releases) -* [crates.io](https://crates.io/crates/euclid) diff --git a/third_party/rust/euclid-0.17.3/src/approxeq.rs b/third_party/rust/euclid-0.17.3/src/approxeq.rs deleted file mode 100644 index 9fb11cc3beba..000000000000 --- a/third_party/rust/euclid-0.17.3/src/approxeq.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Trait for testing approximate equality -pub trait ApproxEq { - fn approx_epsilon() -> Eps; - fn approx_eq(&self, other: &Self) -> bool; - fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool; -} - -macro_rules! approx_eq { - ($ty:ty, $eps:expr) => ( - impl ApproxEq<$ty> for $ty { - #[inline] - fn approx_epsilon() -> $ty { $eps } - #[inline] - fn approx_eq(&self, other: &$ty) -> bool { - self.approx_eq_eps(other, &$eps) - } - #[inline] - fn approx_eq_eps(&self, other: &$ty, approx_epsilon: &$ty) -> bool { - (*self - *other).abs() < *approx_epsilon - } - } - ) -} - -approx_eq!(f32, 1.0e-6); -approx_eq!(f64, 1.0e-6); diff --git a/third_party/rust/euclid-0.17.3/src/homogen.rs b/third_party/rust/euclid-0.17.3/src/homogen.rs deleted file mode 100644 index c48f00d3cf72..000000000000 --- a/third_party/rust/euclid-0.17.3/src/homogen.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2018 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use point::{TypedPoint2D, TypedPoint3D}; -use vector::{TypedVector2D, TypedVector3D}; - -use num::{One, Zero}; - -use std::fmt; -use std::marker::PhantomData; -use std::ops::Div; - - -define_matrix! { - /// Homogeneous vector in 3D space. - pub struct HomogeneousVector { - pub x: T, - pub y: T, - pub z: T, - pub w: T, - } -} - - -impl HomogeneousVector { - /// Constructor taking scalar values directly. - #[inline] - pub fn new(x: T, y: T, z: T, w: T) -> Self { - HomogeneousVector { x, y, z, w, _unit: PhantomData } - } -} - - -impl, U> HomogeneousVector { - /// Convert into Cartesian 2D point. - /// - /// Note: possible division by zero. - #[inline] - pub fn to_point2d(&self) -> TypedPoint2D { - TypedPoint2D::new(self.x / self.w, self.y / self.w) - } - - /// Convert into Cartesian 3D point. - /// - /// Note: possible division by zero. - #[inline] - pub fn to_point3d(&self) -> TypedPoint3D { - TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w) - } -} - -impl From> for HomogeneousVector { - #[inline] - fn from(v: TypedVector2D) -> Self { - HomogeneousVector::new(v.x, v.y, T::zero(), T::zero()) - } -} - -impl From> for HomogeneousVector { - #[inline] - fn from(v: TypedVector3D) -> Self { - HomogeneousVector::new(v.x, v.y, v.z, T::zero()) - } -} - -impl From> for HomogeneousVector { - #[inline] - fn from(p: TypedPoint2D) -> Self { - HomogeneousVector::new(p.x, p.y, T::zero(), T::one()) - } -} - -impl From> for HomogeneousVector { - #[inline] - fn from(p: TypedPoint3D) -> Self { - HomogeneousVector::new(p.x, p.y, p.z, T::one()) - } -} - -impl fmt::Debug for HomogeneousVector { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?},{:?},{:?},{:?})", self.x, self.y, self.z, self.w) - } -} - -impl fmt::Display for HomogeneousVector { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "({},{},{},{})", self.x, self.y, self.z, self.w) - } -} - - -#[cfg(test)] -mod homogeneous { - use super::HomogeneousVector; - use point::{Point2D, Point3D}; - - #[test] - fn roundtrip() { - assert_eq!(Point2D::new(1.0, 2.0), HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d()); - assert_eq!(Point3D::new(1.0, -2.0, 0.1), HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d()); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/length.rs b/third_party/rust/euclid-0.17.3/src/length.rs deleted file mode 100644 index 8a7caff4c895..000000000000 --- a/third_party/rust/euclid-0.17.3/src/length.rs +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright 2014 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -//! A one-dimensional length, tagged with its units. - -use scale::TypedScale; -use num::Zero; - -use num_traits::{NumCast, Saturating}; -use num::One; -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::cmp::Ordering; -use std::ops::{Add, Div, Mul, Neg, Sub}; -use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign}; -use std::marker::PhantomData; -use std::fmt; - -/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`. -/// -/// `T` can be any numeric type, for example a primitive type like `u64` or `f32`. -/// -/// `Unit` is not used in the representation of a `Length` value. It is used only at compile time -/// to ensure that a `Length` stored with one unit is converted explicitly before being used in an -/// expression that requires a different unit. It may be a type without values, such as an empty -/// enum. -/// -/// You can multiply a `Length` by a `scale::TypedScale` to convert it from one unit to -/// another. See the [`TypedScale`] docs for an example. -/// -/// [`TypedScale`]: struct.TypedScale.html -#[repr(C)] -pub struct Length(pub T, PhantomData); - -impl Clone for Length { - fn clone(&self) -> Self { - Length(self.0.clone(), PhantomData) - } -} - -impl Copy for Length {} - -#[cfg(feature = "serde")] -impl<'de, Unit, T> Deserialize<'de> for Length -where - T: Deserialize<'de>, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Length( - try!(Deserialize::deserialize(deserializer)), - PhantomData, - )) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Length -where - T: Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl Length { - pub fn new(x: T) -> Self { - Length(x, PhantomData) - } -} - -impl Length { - pub fn get(&self) -> T { - self.0.clone() - } -} - -impl fmt::Debug for Length { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.get().fmt(f) - } -} - -impl fmt::Display for Length { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.get().fmt(f) - } -} - -// length + length -impl> Add for Length { - type Output = Length; - fn add(self, other: Length) -> Length { - Length::new(self.get() + other.get()) - } -} - -// length += length -impl> AddAssign for Length { - fn add_assign(&mut self, other: Length) { - self.0 += other.get(); - } -} - -// length - length -impl> Sub> for Length { - type Output = Length; - fn sub(self, other: Length) -> ::Output { - Length::new(self.get() - other.get()) - } -} - -// length -= length -impl> SubAssign for Length { - fn sub_assign(&mut self, other: Length) { - self.0 -= other.get(); - } -} - -// Saturating length + length and length - length. -impl Saturating for Length { - fn saturating_add(self, other: Length) -> Length { - Length::new(self.get().saturating_add(other.get())) - } - - fn saturating_sub(self, other: Length) -> Length { - Length::new(self.get().saturating_sub(other.get())) - } -} - -// length / length -impl> Div> for Length { - type Output = TypedScale; - #[inline] - fn div(self, other: Length) -> TypedScale { - TypedScale::new(self.get() / other.get()) - } -} - -// length * scalar -impl, U> Mul for Length { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - Length::new(self.get() * scale) - } -} - -// length *= scalar -impl, U> MulAssign for Length { - #[inline] - fn mul_assign(&mut self, scale: T) { - *self = *self * scale - } -} - -// length / scalar -impl, U> Div for Length { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - Length::new(self.get() / scale) - } -} - -// length /= scalar -impl, U> DivAssign for Length { - #[inline] - fn div_assign(&mut self, scale: T) { - *self = *self / scale - } -} - -// length * scaleFactor -impl> Mul> for Length { - type Output = Length; - #[inline] - fn mul(self, scale: TypedScale) -> Length { - Length::new(self.get() * scale.get()) - } -} - -// length / scaleFactor -impl> Div> for Length { - type Output = Length; - #[inline] - fn div(self, scale: TypedScale) -> Length { - Length::new(self.get() / scale.get()) - } -} - -// -length -impl> Neg for Length { - type Output = Length; - #[inline] - fn neg(self) -> Length { - Length::new(-self.get()) - } -} - -impl Length { - /// Cast from one numeric representation to another, preserving the units. - pub fn cast(&self) -> Option> { - NumCast::from(self.get()).map(Length::new) - } -} - -impl PartialEq for Length { - fn eq(&self, other: &Self) -> bool { - self.get().eq(&other.get()) - } -} - -impl PartialOrd for Length { - fn partial_cmp(&self, other: &Self) -> Option { - self.get().partial_cmp(&other.get()) - } -} - -impl Eq for Length {} - -impl Ord for Length { - fn cmp(&self, other: &Self) -> Ordering { - self.get().cmp(&other.get()) - } -} - -impl Zero for Length { - fn zero() -> Self { - Length::new(Zero::zero()) - } -} - -impl Length -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this length and another length. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - Length::new(one_t * self.get() + t * other.get()) - } -} - -#[cfg(test)] -mod tests { - use super::Length; - use num::Zero; - - use num_traits::Saturating; - use scale::TypedScale; - use std::f32::INFINITY; - - enum Inch {} - enum Mm {} - enum Cm {} - enum Second {} - - #[cfg(feature = "serde")] - mod serde { - use super::*; - - extern crate serde_test; - use self::serde_test::Token; - use self::serde_test::assert_tokens; - - #[test] - fn test_length_serde() { - let one_cm: Length = Length::new(10.0); - - assert_tokens(&one_cm, &[Token::F32(10.0)]); - } - } - - #[test] - fn test_clone() { - // A cloned Length is a separate length with the state matching the - // original Length at the point it was cloned. - let mut variable_length: Length = Length::new(12.0); - - let one_foot = variable_length.clone(); - variable_length.0 = 24.0; - - assert_eq!(one_foot.get(), 12.0); - assert_eq!(variable_length.get(), 24.0); - } - - #[test] - fn test_get_clones_length_value() { - // Calling get returns a clone of the Length's value. - // To test this, we need something clone-able - hence a vector. - let mut length: Length, Inch> = Length::new(vec![1, 2, 3]); - - let value = length.get(); - length.0.push(4); - - assert_eq!(value, vec![1, 2, 3]); - assert_eq!(length.get(), vec![1, 2, 3, 4]); - } - - #[test] - fn test_add() { - let length1: Length = Length::new(250); - let length2: Length = Length::new(5); - - let result = length1 + length2; - - assert_eq!(result.get(), 255); - } - - #[test] - fn test_addassign() { - let one_cm: Length = Length::new(10.0); - let mut measurement: Length = Length::new(5.0); - - measurement += one_cm; - - assert_eq!(measurement.get(), 15.0); - } - - #[test] - fn test_sub() { - let length1: Length = Length::new(250); - let length2: Length = Length::new(5); - - let result = length1 - length2; - - assert_eq!(result.get(), 245); - } - - #[test] - fn test_subassign() { - let one_cm: Length = Length::new(10.0); - let mut measurement: Length = Length::new(5.0); - - measurement -= one_cm; - - assert_eq!(measurement.get(), -5.0); - } - - #[test] - fn test_saturating_add() { - let length1: Length = Length::new(250); - let length2: Length = Length::new(6); - - let result = length1.saturating_add(length2); - - assert_eq!(result.get(), 255); - } - - #[test] - fn test_saturating_sub() { - let length1: Length = Length::new(5); - let length2: Length = Length::new(10); - - let result = length1.saturating_sub(length2); - - assert_eq!(result.get(), 0); - } - - #[test] - fn test_division_by_length() { - // Division results in a TypedScale from denominator units - // to numerator units. - let length: Length = Length::new(5.0); - let duration: Length = Length::new(10.0); - - let result = length / duration; - - let expected: TypedScale = TypedScale::new(0.5); - assert_eq!(result, expected); - } - - #[test] - fn test_multiplication() { - let length_mm: Length = Length::new(10.0); - let cm_per_mm: TypedScale = TypedScale::new(0.1); - - let result = length_mm * cm_per_mm; - - let expected: Length = Length::new(1.0); - assert_eq!(result, expected); - } - - #[test] - fn test_multiplication_with_scalar() { - let length_mm: Length = Length::new(10.0); - - let result = length_mm * 2.0; - - let expected: Length = Length::new(20.0); - assert_eq!(result, expected); - } - - #[test] - fn test_multiplication_assignment() { - let mut length: Length = Length::new(10.0); - - length *= 2.0; - - let expected: Length = Length::new(20.0); - assert_eq!(length, expected); - } - - #[test] - fn test_division_by_scalefactor() { - let length: Length = Length::new(5.0); - let cm_per_second: TypedScale = TypedScale::new(10.0); - - let result = length / cm_per_second; - - let expected: Length = Length::new(0.5); - assert_eq!(result, expected); - } - - #[test] - fn test_division_by_scalar() { - let length: Length = Length::new(5.0); - - let result = length / 2.0; - - let expected: Length = Length::new(2.5); - assert_eq!(result, expected); - } - - #[test] - fn test_division_assignment() { - let mut length: Length = Length::new(10.0); - - length /= 2.0; - - let expected: Length = Length::new(5.0); - assert_eq!(length, expected); - } - - #[test] - fn test_negation() { - let length: Length = Length::new(5.0); - - let result = -length; - - let expected: Length = Length::new(-5.0); - assert_eq!(result, expected); - } - - #[test] - fn test_cast() { - let length_as_i32: Length = Length::new(5); - - let result: Length = length_as_i32.cast().unwrap(); - - let length_as_f32: Length = Length::new(5.0); - assert_eq!(result, length_as_f32); - } - - #[test] - fn test_equality() { - let length_5_point_0: Length = Length::new(5.0); - let length_5_point_1: Length = Length::new(5.1); - let length_0_point_1: Length = Length::new(0.1); - - assert!(length_5_point_0 == length_5_point_1 - length_0_point_1); - assert!(length_5_point_0 != length_5_point_1); - } - - #[test] - fn test_order() { - let length_5_point_0: Length = Length::new(5.0); - let length_5_point_1: Length = Length::new(5.1); - let length_0_point_1: Length = Length::new(0.1); - - assert!(length_5_point_0 < length_5_point_1); - assert!(length_5_point_0 <= length_5_point_1); - assert!(length_5_point_0 <= length_5_point_1 - length_0_point_1); - assert!(length_5_point_1 > length_5_point_0); - assert!(length_5_point_1 >= length_5_point_0); - assert!(length_5_point_0 >= length_5_point_1 - length_0_point_1); - } - - #[test] - fn test_zero_add() { - type LengthCm = Length; - let length: LengthCm = Length::new(5.0); - - let result = length - LengthCm::zero(); - - assert_eq!(result, length); - } - - #[test] - fn test_zero_division() { - type LengthCm = Length; - let length: LengthCm = Length::new(5.0); - let length_zero: LengthCm = Length::zero(); - - let result = length / length_zero; - - let expected: TypedScale = TypedScale::new(INFINITY); - assert_eq!(result, expected); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/lib.rs b/third_party/rust/euclid-0.17.3/src/lib.rs deleted file mode 100644 index 3198f0d3e359..000000000000 --- a/third_party/rust/euclid-0.17.3/src/lib.rs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![cfg_attr(feature = "unstable", feature(fn_must_use))] - -//! A collection of strongly typed math tools for computer graphics with an inclination -//! towards 2d graphics and layout. -//! -//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.), -//! and tagged with a generic Unit parameter which is useful to prevent mixing -//! values from different spaces. For example it should not be legal to translate -//! a screen-space position by a world-space vector and this can be expressed using -//! the generic Unit parameter. -//! -//! This unit system is not mandatory and all Typed* structures have an alias -//! with the default unit: `UnknownUnit`. -//! for example ```Point2D``` is equivalent to ```TypedPoint2D```. -//! Client code typically creates a set of aliases for each type and doesn't need -//! to deal with the specifics of typed units further. For example: -//! -//! ```rust -//! use euclid::*; -//! pub struct ScreenSpace; -//! pub type ScreenPoint = TypedPoint2D; -//! pub type ScreenSize = TypedSize2D; -//! pub struct WorldSpace; -//! pub type WorldPoint = TypedPoint3D; -//! pub type ProjectionMatrix = TypedTransform3D; -//! // etc... -//! ``` -//! -//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to -//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`). -//! -//! Components are accessed in their scalar form by default for convenience, and most -//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers. -//! For example: -//! -//! ```rust -//! # use euclid::*; -//! # pub struct WorldSpace; -//! # pub type WorldPoint = TypedPoint3D; -//! let p = WorldPoint::new(0.0, 1.0, 1.0); -//! // p.x is an f32. -//! println!("p.x = {:?} ", p.x); -//! // p.x is a Length. -//! println!("p.x_typed() = {:?} ", p.x_typed()); -//! // Length::get returns the scalar value (f32). -//! assert_eq!(p.x, p.x_typed().get()); -//! ``` - -#[cfg(feature = "serde")] -#[macro_use] -extern crate serde; - -extern crate num_traits; -#[cfg(test)] -extern crate rand; - -pub use length::Length; -pub use scale::TypedScale; -pub use transform2d::{Transform2D, TypedTransform2D}; -pub use transform3d::{Transform3D, TypedTransform3D}; -pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3}; -pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3}; -pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3}; -pub use homogen::HomogeneousVector; - -pub use rect::{rect, Rect, TypedRect}; -pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D}; -pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D}; -pub use size::{Size2D, TypedSize2D, size2}; -pub use trig::Trig; - -#[macro_use] -mod macros; - -pub mod approxeq; -mod homogen; -pub mod num; -mod length; -mod point; -mod rect; -mod rotation; -mod scale; -mod side_offsets; -mod size; -mod transform2d; -mod transform3d; -mod trig; -mod vector; - -/// The default unit. -#[derive(Clone, Copy)] -pub struct UnknownUnit; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub type Matrix2D = Transform2D; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub type TypedMatrix2D = TypedTransform2D; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub type Matrix4D = Transform3D; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub type TypedMatrix4D = TypedTransform3D; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub type ScaleFactor = TypedScale; - -/// Temporary alias to facilitate the transition to the new naming scheme -#[deprecated] -pub use Angle as Radians; - diff --git a/third_party/rust/euclid-0.17.3/src/macros.rs b/third_party/rust/euclid-0.17.3/src/macros.rs deleted file mode 100644 index b0a455bcca23..000000000000 --- a/third_party/rust/euclid-0.17.3/src/macros.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -macro_rules! define_matrix { - ( - $(#[$attr:meta])* - pub struct $name:ident { - $(pub $field:ident: T,)+ - } - ) => ( - #[repr(C)] - $(#[$attr])* - pub struct $name { - $(pub $field: T,)+ - _unit: PhantomData<($($phantom),+)> - } - - impl Clone for $name { - fn clone(&self) -> Self { - $name { - $($field: self.$field.clone(),)+ - _unit: PhantomData, - } - } - } - - impl Copy for $name {} - - #[cfg(feature = "serde")] - impl<'de, T, $($phantom),+> ::serde::Deserialize<'de> for $name - where T: ::serde::Deserialize<'de> - { - fn deserialize(deserializer: D) -> Result - where D: ::serde::Deserializer<'de> - { - let ($($field,)+) = - try!(::serde::Deserialize::deserialize(deserializer)); - Ok($name { - $($field: $field,)+ - _unit: PhantomData, - }) - } - } - - #[cfg(feature = "serde")] - impl ::serde::Serialize for $name - where T: ::serde::Serialize - { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::Serializer - { - ($(&self.$field,)+).serialize(serializer) - } - } - - impl ::std::cmp::Eq for $name - where T: ::std::cmp::Eq {} - - impl ::std::cmp::PartialEq for $name - where T: ::std::cmp::PartialEq - { - fn eq(&self, other: &Self) -> bool { - true $(&& self.$field == other.$field)+ - } - } - - impl ::std::hash::Hash for $name - where T: ::std::hash::Hash - { - fn hash(&self, h: &mut H) { - $(self.$field.hash(h);)+ - } - } - ) -} diff --git a/third_party/rust/euclid-0.17.3/src/num.rs b/third_party/rust/euclid-0.17.3/src/num.rs deleted file mode 100644 index 1df86d75336a..000000000000 --- a/third_party/rust/euclid-0.17.3/src/num.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2014 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -//! A one-dimensional length, tagged with its units. - -use num_traits; - -pub trait Zero { - fn zero() -> Self; -} - -impl Zero for T { - fn zero() -> T { - num_traits::Zero::zero() - } -} - -pub trait One { - fn one() -> Self; -} - -impl One for T { - fn one() -> T { - num_traits::One::one() - } -} - -pub trait Round: Copy { - fn round(self) -> Self; -} -pub trait Floor: Copy { - fn floor(self) -> Self; -} -pub trait Ceil: Copy { - fn ceil(self) -> Self; -} - -macro_rules! num_int { - ($ty:ty) => ( - impl Round for $ty { - #[inline] - fn round(self) -> $ty { self } - } - impl Floor for $ty { - #[inline] - fn floor(self) -> $ty { self } - } - impl Ceil for $ty { - #[inline] - fn ceil(self) -> $ty { self } - } - ) -} -macro_rules! num_float { - ($ty:ty) => ( - impl Round for $ty { - #[inline] - fn round(self) -> $ty { self.round() } - } - impl Floor for $ty { - #[inline] - fn floor(self) -> $ty { self.floor() } - } - impl Ceil for $ty { - #[inline] - fn ceil(self) -> $ty { self.ceil() } - } - ) -} - -num_int!(i16); -num_int!(u16); -num_int!(i32); -num_int!(u32); -num_int!(i64); -num_int!(u64); -num_int!(isize); -num_int!(usize); -num_float!(f32); -num_float!(f64); diff --git a/third_party/rust/euclid-0.17.3/src/point.rs b/third_party/rust/euclid-0.17.3/src/point.rs deleted file mode 100644 index a6a6cde4f2c1..000000000000 --- a/third_party/rust/euclid-0.17.3/src/point.rs +++ /dev/null @@ -1,899 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::UnknownUnit; -use approxeq::ApproxEq; -use length::Length; -use scale::TypedScale; -use size::TypedSize2D; -use num::*; -use num_traits::{Float, NumCast}; -use vector::{TypedVector2D, TypedVector3D, vec2, vec3}; -use std::fmt; -use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; -use std::marker::PhantomData; - -define_matrix! { - /// A 2d Point tagged with a unit. - pub struct TypedPoint2D { - pub x: T, - pub y: T, - } -} - -/// Default 2d point type with no unit. -/// -/// `Point2D` provides the same methods as `TypedPoint2D`. -pub type Point2D = TypedPoint2D; - -impl TypedPoint2D { - /// Constructor, setting all components to zero. - #[inline] - pub fn origin() -> Self { - point2(Zero::zero(), Zero::zero()) - } - - #[inline] - pub fn zero() -> Self { - Self::origin() - } - - /// Convert into a 3d point. - #[inline] - pub fn to_3d(&self) -> TypedPoint3D { - point3(self.x, self.y, Zero::zero()) - } -} - -impl fmt::Debug for TypedPoint2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?},{:?})", self.x, self.y) - } -} - -impl fmt::Display for TypedPoint2D { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "({},{})", self.x, self.y) - } -} - -impl TypedPoint2D { - /// Constructor taking scalar values directly. - #[inline] - pub fn new(x: T, y: T) -> Self { - TypedPoint2D { - x: x, - y: y, - _unit: PhantomData, - } - } -} - -impl TypedPoint2D { - /// Constructor taking properly typed Lengths instead of scalar values. - #[inline] - pub fn from_lengths(x: Length, y: Length) -> Self { - point2(x.0, y.0) - } - - /// Create a 3d point from this one, using the specified z value. - #[inline] - pub fn extend(&self, z: T) -> TypedPoint3D { - point3(self.x, self.y, z) - } - - /// Cast this point into a vector. - /// - /// Equivalent to subtracting the origin from this point. - #[inline] - pub fn to_vector(&self) -> TypedVector2D { - vec2(self.x, self.y) - } - - /// Swap x and y. - #[inline] - pub fn yx(&self) -> Self { - point2(self.y, self.x) - } - - /// Returns self.x as a Length carrying the unit. - #[inline] - pub fn x_typed(&self) -> Length { - Length::new(self.x) - } - - /// Returns self.y as a Length carrying the unit. - #[inline] - pub fn y_typed(&self) -> Length { - Length::new(self.y) - } - - /// Drop the units, preserving only the numeric value. - #[inline] - pub fn to_untyped(&self) -> Point2D { - point2(self.x, self.y) - } - - /// Tag a unitless value with units. - #[inline] - pub fn from_untyped(p: &Point2D) -> Self { - point2(p.x, p.y) - } - - #[inline] - pub fn to_array(&self) -> [T; 2] { - [self.x, self.y] - } -} - -impl, U> TypedPoint2D { - #[inline] - pub fn add_size(&self, other: &TypedSize2D) -> Self { - point2(self.x + other.width, self.y + other.height) - } -} - -impl, U> Add> for TypedPoint2D { - type Output = Self; - #[inline] - fn add(self, other: TypedSize2D) -> Self { - point2(self.x + other.width, self.y + other.height) - } -} - -impl, U> AddAssign> for TypedPoint2D { - #[inline] - fn add_assign(&mut self, other: TypedVector2D) { - *self = *self + other - } -} - -impl, U> SubAssign> for TypedPoint2D { - #[inline] - fn sub_assign(&mut self, other: TypedVector2D) { - *self = *self - other - } -} - -impl, U> Add> for TypedPoint2D { - type Output = Self; - #[inline] - fn add(self, other: TypedVector2D) -> Self { - point2(self.x + other.x, self.y + other.y) - } -} - -impl, U> Sub for TypedPoint2D { - type Output = TypedVector2D; - #[inline] - fn sub(self, other: Self) -> TypedVector2D { - vec2(self.x - other.x, self.y - other.y) - } -} - -impl, U> Sub> for TypedPoint2D { - type Output = Self; - #[inline] - fn sub(self, other: TypedVector2D) -> Self { - point2(self.x - other.x, self.y - other.y) - } -} - -impl TypedPoint2D { - #[inline] - pub fn min(self, other: Self) -> Self { - point2(self.x.min(other.x), self.y.min(other.y)) - } - - #[inline] - pub fn max(self, other: Self) -> Self { - point2(self.x.max(other.x), self.y.max(other.y)) - } -} - -impl, U> Mul for TypedPoint2D { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - point2(self.x * scale, self.y * scale) - } -} - -impl, U> MulAssign for TypedPoint2D { - #[inline] - fn mul_assign(&mut self, scale: T) { - *self = *self * scale - } -} - -impl, U> Div for TypedPoint2D { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - point2(self.x / scale, self.y / scale) - } -} - -impl, U> DivAssign for TypedPoint2D { - #[inline] - fn div_assign(&mut self, scale: T) { - *self = *self / scale - } -} - -impl, U1, U2> Mul> for TypedPoint2D { - type Output = TypedPoint2D; - #[inline] - fn mul(self, scale: TypedScale) -> TypedPoint2D { - point2(self.x * scale.get(), self.y * scale.get()) - } -} - -impl, U1, U2> Div> for TypedPoint2D { - type Output = TypedPoint2D; - #[inline] - fn div(self, scale: TypedScale) -> TypedPoint2D { - point2(self.x / scale.get(), self.y / scale.get()) - } -} - -impl TypedPoint2D { - /// Rounds each component to the nearest integer value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.round() == { 0.0, -1.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn round(&self) -> Self { - point2(self.x.round(), self.y.round()) - } -} - -impl TypedPoint2D { - /// Rounds each component to the smallest integer equal or greater than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.ceil() == { 0.0, 0.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn ceil(&self) -> Self { - point2(self.x.ceil(), self.y.ceil()) - } -} - -impl TypedPoint2D { - /// Rounds each component to the biggest integer equal or lower than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.floor() == { -1.0, -1.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn floor(&self) -> Self { - point2(self.x.floor(), self.y.floor()) - } -} - -impl TypedPoint2D { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating point to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. - #[inline] - pub fn cast(&self) -> Option> { - match (NumCast::from(self.x), NumCast::from(self.y)) { - (Some(x), Some(y)) => Some(point2(x, y)), - _ => None, - } - } - - // Convenience functions for common casts - - /// Cast into an `f32` point. - #[inline] - pub fn to_f32(&self) -> TypedPoint2D { - self.cast().unwrap() - } - - /// Cast into an `f64` point. - #[inline] - pub fn to_f64(&self) -> TypedPoint2D { - self.cast().unwrap() - } - - /// Cast into an `usize` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_usize(&self) -> TypedPoint2D { - self.cast().unwrap() - } - - /// Cast into an `u32` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_u32(&self) -> TypedPoint2D { - self.cast().unwrap() - } - - /// Cast into an i32 point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i32(&self) -> TypedPoint2D { - self.cast().unwrap() - } - - /// Cast into an i64 point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i64(&self) -> TypedPoint2D { - self.cast().unwrap() - } -} - -impl TypedPoint2D -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this point and another point. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - point2(one_t * self.x + t * other.x, one_t * self.y + t * other.y) - } -} - -impl, U> ApproxEq> for TypedPoint2D { - #[inline] - fn approx_epsilon() -> Self { - point2(T::approx_epsilon(), T::approx_epsilon()) - } - - #[inline] - fn approx_eq(&self, other: &Self) -> bool { - self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) - } - - #[inline] - fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool { - self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y) - } -} - -impl Into<[T; 2]> for TypedPoint2D { - fn into(self) -> [T; 2] { - self.to_array() - } -} - -impl From<[T; 2]> for TypedPoint2D { - fn from(array: [T; 2]) -> Self { - point2(array[0], array[1]) - } -} - -define_matrix! { - /// A 3d Point tagged with a unit. - pub struct TypedPoint3D { - pub x: T, - pub y: T, - pub z: T, - } -} - -/// Default 3d point type with no unit. -/// -/// `Point3D` provides the same methods as `TypedPoint3D`. -pub type Point3D = TypedPoint3D; - -impl TypedPoint3D { - /// Constructor, setting all components to zero. - #[inline] - pub fn origin() -> Self { - point3(Zero::zero(), Zero::zero(), Zero::zero()) - } -} - -impl TypedPoint3D { - #[inline] - pub fn to_array_4d(&self) -> [T; 4] { - [self.x, self.y, self.z, One::one()] - } -} - -impl TypedPoint3D -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this point and another point. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - point3( - one_t * self.x + t * other.x, - one_t * self.y + t * other.y, - one_t * self.z + t * other.z, - ) - } -} - -impl fmt::Debug for TypedPoint3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z) - } -} - -impl fmt::Display for TypedPoint3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({},{},{})", self.x, self.y, self.z) - } -} - -impl TypedPoint3D { - /// Constructor taking scalar values directly. - #[inline] - pub fn new(x: T, y: T, z: T) -> Self { - TypedPoint3D { - x: x, - y: y, - z: z, - _unit: PhantomData, - } - } - - /// Constructor taking properly typed Lengths instead of scalar values. - #[inline] - pub fn from_lengths(x: Length, y: Length, z: Length) -> Self { - point3(x.0, y.0, z.0) - } - - /// Cast this point into a vector. - /// - /// Equivalent to subtracting the origin to this point. - #[inline] - pub fn to_vector(&self) -> TypedVector3D { - vec3(self.x, self.y, self.z) - } - - /// Returns a 2d point using this point's x and y coordinates - #[inline] - pub fn xy(&self) -> TypedPoint2D { - point2(self.x, self.y) - } - - /// Returns a 2d point using this point's x and z coordinates - #[inline] - pub fn xz(&self) -> TypedPoint2D { - point2(self.x, self.z) - } - - /// Returns a 2d point using this point's x and z coordinates - #[inline] - pub fn yz(&self) -> TypedPoint2D { - point2(self.y, self.z) - } - - /// Returns self.x as a Length carrying the unit. - #[inline] - pub fn x_typed(&self) -> Length { - Length::new(self.x) - } - - /// Returns self.y as a Length carrying the unit. - #[inline] - pub fn y_typed(&self) -> Length { - Length::new(self.y) - } - - /// Returns self.z as a Length carrying the unit. - #[inline] - pub fn z_typed(&self) -> Length { - Length::new(self.z) - } - - #[inline] - pub fn to_array(&self) -> [T; 3] { - [self.x, self.y, self.z] - } - - /// Drop the units, preserving only the numeric value. - #[inline] - pub fn to_untyped(&self) -> Point3D { - point3(self.x, self.y, self.z) - } - - /// Tag a unitless value with units. - #[inline] - pub fn from_untyped(p: &Point3D) -> Self { - point3(p.x, p.y, p.z) - } - - /// Convert into a 2d point. - #[inline] - pub fn to_2d(&self) -> TypedPoint2D { - self.xy() - } -} - -impl, U> AddAssign> for TypedPoint3D { - #[inline] - fn add_assign(&mut self, other: TypedVector3D) { - *self = *self + other - } -} - -impl, U> SubAssign> for TypedPoint3D { - #[inline] - fn sub_assign(&mut self, other: TypedVector3D) { - *self = *self - other - } -} - -impl, U> Add> for TypedPoint3D { - type Output = Self; - #[inline] - fn add(self, other: TypedVector3D) -> Self { - point3(self.x + other.x, self.y + other.y, self.z + other.z) - } -} - -impl, U> Sub for TypedPoint3D { - type Output = TypedVector3D; - #[inline] - fn sub(self, other: Self) -> TypedVector3D { - vec3(self.x - other.x, self.y - other.y, self.z - other.z) - } -} - -impl, U> Sub> for TypedPoint3D { - type Output = Self; - #[inline] - fn sub(self, other: TypedVector3D) -> Self { - point3(self.x - other.x, self.y - other.y, self.z - other.z) - } -} - -impl, U> Mul for TypedPoint3D { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - point3(self.x * scale, self.y * scale, self.z * scale) - } -} - -impl, U> Div for TypedPoint3D { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - point3(self.x / scale, self.y / scale, self.z / scale) - } -} - -impl TypedPoint3D { - #[inline] - pub fn min(self, other: Self) -> Self { - point3( - self.x.min(other.x), - self.y.min(other.y), - self.z.min(other.z), - ) - } - - #[inline] - pub fn max(self, other: Self) -> Self { - point3( - self.x.max(other.x), - self.y.max(other.y), - self.z.max(other.z), - ) - } -} - -impl TypedPoint3D { - /// Rounds each component to the nearest integer value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn round(&self) -> Self { - point3(self.x.round(), self.y.round(), self.z.round()) - } -} - -impl TypedPoint3D { - /// Rounds each component to the smallest integer equal or greater than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn ceil(&self) -> Self { - point3(self.x.ceil(), self.y.ceil(), self.z.ceil()) - } -} - -impl TypedPoint3D { - /// Rounds each component to the biggest integer equal or lower than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn floor(&self) -> Self { - point3(self.x.floor(), self.y.floor(), self.z.floor()) - } -} - -impl TypedPoint3D { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating point to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. - #[inline] - pub fn cast(&self) -> Option> { - match ( - NumCast::from(self.x), - NumCast::from(self.y), - NumCast::from(self.z), - ) { - (Some(x), Some(y), Some(z)) => Some(point3(x, y, z)), - _ => None, - } - } - - // Convenience functions for common casts - - /// Cast into an `f32` point. - #[inline] - pub fn to_f32(&self) -> TypedPoint3D { - self.cast().unwrap() - } - - /// Cast into an `f64` point. - #[inline] - pub fn to_f64(&self) -> TypedPoint3D { - self.cast().unwrap() - } - - /// Cast into an `usize` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_usize(&self) -> TypedPoint3D { - self.cast().unwrap() - } - - /// Cast into an `u32` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_u32(&self) -> TypedPoint3D { - self.cast().unwrap() - } - - /// Cast into an `i32` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i32(&self) -> TypedPoint3D { - self.cast().unwrap() - } - - /// Cast into an `i64` point, truncating decimals if any. - /// - /// When casting from floating point points, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i64(&self) -> TypedPoint3D { - self.cast().unwrap() - } -} - -impl, U> ApproxEq> for TypedPoint3D { - #[inline] - fn approx_epsilon() -> Self { - point3( - T::approx_epsilon(), - T::approx_epsilon(), - T::approx_epsilon(), - ) - } - - #[inline] - fn approx_eq(&self, other: &Self) -> bool { - self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) && self.z.approx_eq(&other.z) - } - - #[inline] - fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool { - self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y) - && self.z.approx_eq_eps(&other.z, &eps.z) - } -} - -impl Into<[T; 3]> for TypedPoint3D { - fn into(self) -> [T; 3] { - self.to_array() - } -} - -impl From<[T; 3]> for TypedPoint3D { - fn from(array: [T; 3]) -> Self { - point3(array[0], array[1], array[2]) - } -} - -pub fn point2(x: T, y: T) -> TypedPoint2D { - TypedPoint2D::new(x, y) -} - -pub fn point3(x: T, y: T, z: T) -> TypedPoint3D { - TypedPoint3D::new(x, y, z) -} - -#[cfg(test)] -mod point2d { - use super::Point2D; - - #[test] - pub fn test_scalar_mul() { - let p1: Point2D = Point2D::new(3.0, 5.0); - - let result = p1 * 5.0; - - assert_eq!(result, Point2D::new(15.0, 25.0)); - } - - #[test] - pub fn test_min() { - let p1 = Point2D::new(1.0, 3.0); - let p2 = Point2D::new(2.0, 2.0); - - let result = p1.min(p2); - - assert_eq!(result, Point2D::new(1.0, 2.0)); - } - - #[test] - pub fn test_max() { - let p1 = Point2D::new(1.0, 3.0); - let p2 = Point2D::new(2.0, 2.0); - - let result = p1.max(p2); - - assert_eq!(result, Point2D::new(2.0, 3.0)); - } -} - -#[cfg(test)] -mod typedpoint2d { - use super::{Point2D, TypedPoint2D, point2}; - use scale::TypedScale; - use vector::vec2; - - pub enum Mm {} - pub enum Cm {} - - pub type Point2DMm = TypedPoint2D; - pub type Point2DCm = TypedPoint2D; - - #[test] - pub fn test_add() { - let p1 = Point2DMm::new(1.0, 2.0); - let p2 = vec2(3.0, 4.0); - - let result = p1 + p2; - - assert_eq!(result, Point2DMm::new(4.0, 6.0)); - } - - #[test] - pub fn test_add_assign() { - let mut p1 = Point2DMm::new(1.0, 2.0); - p1 += vec2(3.0, 4.0); - - assert_eq!(p1, Point2DMm::new(4.0, 6.0)); - } - - #[test] - pub fn test_scalar_mul() { - let p1 = Point2DMm::new(1.0, 2.0); - let cm_per_mm: TypedScale = TypedScale::new(0.1); - - let result = p1 * cm_per_mm; - - assert_eq!(result, Point2DCm::new(0.1, 0.2)); - } - - #[test] - pub fn test_conv_vector() { - use {Point2D, point2}; - - for i in 0..100 { - // We don't care about these values as long as they are not the same. - let x = i as f32 * 0.012345; - let y = i as f32 * 0.987654; - let p: Point2D = point2(x, y); - assert_eq!(p.to_vector().to_point(), p); - } - } - - #[test] - pub fn test_swizzling() { - let p: Point2D = point2(1, 2); - assert_eq!(p.yx(), point2(2, 1)); - } -} - -#[cfg(test)] -mod point3d { - use super::{Point3D, point2, point3}; - - #[test] - pub fn test_min() { - let p1 = Point3D::new(1.0, 3.0, 5.0); - let p2 = Point3D::new(2.0, 2.0, -1.0); - - let result = p1.min(p2); - - assert_eq!(result, Point3D::new(1.0, 2.0, -1.0)); - } - - #[test] - pub fn test_max() { - let p1 = Point3D::new(1.0, 3.0, 5.0); - let p2 = Point3D::new(2.0, 2.0, -1.0); - - let result = p1.max(p2); - - assert_eq!(result, Point3D::new(2.0, 3.0, 5.0)); - } - - #[test] - pub fn test_conv_vector() { - use point3; - for i in 0..100 { - // We don't care about these values as long as they are not the same. - let x = i as f32 * 0.012345; - let y = i as f32 * 0.987654; - let z = x * y; - let p: Point3D = point3(x, y, z); - assert_eq!(p.to_vector().to_point(), p); - } - } - - #[test] - pub fn test_swizzling() { - let p: Point3D = point3(1, 2, 3); - assert_eq!(p.xy(), point2(1, 2)); - assert_eq!(p.xz(), point2(1, 3)); - assert_eq!(p.yz(), point2(2, 3)); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/rect.rs b/third_party/rust/euclid-0.17.3/src/rect.rs deleted file mode 100644 index 750d15cb6a99..000000000000 --- a/third_party/rust/euclid-0.17.3/src/rect.rs +++ /dev/null @@ -1,805 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::UnknownUnit; -use length::Length; -use scale::TypedScale; -use num::*; -use point::TypedPoint2D; -use vector::TypedVector2D; -use side_offsets::TypedSideOffsets2D; -use size::TypedSize2D; - -use num_traits::NumCast; -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -use std::borrow::Borrow; -use std::cmp::PartialOrd; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::ops::{Add, Div, Mul, Sub}; - - -/// A 2d Rectangle optionally tagged with a unit. -#[repr(C)] -pub struct TypedRect { - pub origin: TypedPoint2D, - pub size: TypedSize2D, -} - -/// The default rectangle type with no unit. -pub type Rect = TypedRect; - -#[cfg(feature = "serde")] -impl<'de, T: Copy + Deserialize<'de>, U> Deserialize<'de> for TypedRect { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let (origin, size) = try!(Deserialize::deserialize(deserializer)); - Ok(TypedRect::new(origin, size)) - } -} - -#[cfg(feature = "serde")] -impl Serialize for TypedRect { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - (&self.origin, &self.size).serialize(serializer) - } -} - -impl Hash for TypedRect { - fn hash(&self, h: &mut H) { - self.origin.hash(h); - self.size.hash(h); - } -} - -impl Copy for TypedRect {} - -impl Clone for TypedRect { - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq> for TypedRect { - fn eq(&self, other: &Self) -> bool { - self.origin.eq(&other.origin) && self.size.eq(&other.size) - } -} - -impl Eq for TypedRect {} - -impl fmt::Debug for TypedRect { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TypedRect({:?} at {:?})", self.size, self.origin) - } -} - -impl fmt::Display for TypedRect { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "Rect({} at {})", self.size, self.origin) - } -} - -impl TypedRect { - /// Constructor. - pub fn new(origin: TypedPoint2D, size: TypedSize2D) -> Self { - TypedRect { - origin: origin, - size: size, - } - } -} - -impl TypedRect -where - T: Copy + Clone + Zero + PartialOrd + PartialEq + Add + Sub, -{ - #[inline] - pub fn intersects(&self, other: &Self) -> bool { - self.origin.x < other.origin.x + other.size.width - && other.origin.x < self.origin.x + self.size.width - && self.origin.y < other.origin.y + other.size.height - && other.origin.y < self.origin.y + self.size.height - } - - #[inline] - pub fn max_x(&self) -> T { - self.origin.x + self.size.width - } - - #[inline] - pub fn min_x(&self) -> T { - self.origin.x - } - - #[inline] - pub fn max_y(&self) -> T { - self.origin.y + self.size.height - } - - #[inline] - pub fn min_y(&self) -> T { - self.origin.y - } - - #[inline] - pub fn max_x_typed(&self) -> Length { - Length::new(self.max_x()) - } - - #[inline] - pub fn min_x_typed(&self) -> Length { - Length::new(self.min_x()) - } - - #[inline] - pub fn max_y_typed(&self) -> Length { - Length::new(self.max_y()) - } - - #[inline] - pub fn min_y_typed(&self) -> Length { - Length::new(self.min_y()) - } - - #[inline] - pub fn intersection(&self, other: &Self) -> Option { - if !self.intersects(other) { - return None; - } - - let upper_left = TypedPoint2D::new( - max(self.min_x(), other.min_x()), - max(self.min_y(), other.min_y()), - ); - let lower_right_x = min(self.max_x(), other.max_x()); - let lower_right_y = min(self.max_y(), other.max_y()); - - Some(TypedRect::new( - upper_left, - TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y), - )) - } - - /// Returns the same rectangle, translated by a vector. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn translate(&self, by: &TypedVector2D) -> Self { - Self::new(self.origin + *by, self.size) - } - - /// Returns true if this rectangle contains the point. Points are considered - /// in the rectangle if they are on the left or top edge, but outside if they - /// are on the right or bottom edge. - #[inline] - pub fn contains(&self, other: &TypedPoint2D) -> bool { - self.origin.x <= other.x && other.x < self.origin.x + self.size.width - && self.origin.y <= other.y && other.y < self.origin.y + self.size.height - } - - /// Returns true if this rectangle contains the interior of rect. Always - /// returns true if rect is empty, and always returns false if rect is - /// nonempty but this rectangle is empty. - #[inline] - pub fn contains_rect(&self, rect: &Self) -> bool { - rect.is_empty() - || (self.min_x() <= rect.min_x() && rect.max_x() <= self.max_x() - && self.min_y() <= rect.min_y() && rect.max_y() <= self.max_y()) - } - - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn inflate(&self, width: T, height: T) -> Self { - TypedRect::new( - TypedPoint2D::new(self.origin.x - width, self.origin.y - height), - TypedSize2D::new( - self.size.width + width + width, - self.size.height + height + height, - ), - ) - } - - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn inflate_typed(&self, width: Length, height: Length) -> Self { - self.inflate(width.get(), height.get()) - } - - #[inline] - pub fn top_right(&self) -> TypedPoint2D { - TypedPoint2D::new(self.max_x(), self.origin.y) - } - - #[inline] - pub fn bottom_left(&self) -> TypedPoint2D { - TypedPoint2D::new(self.origin.x, self.max_y()) - } - - #[inline] - pub fn bottom_right(&self) -> TypedPoint2D { - TypedPoint2D::new(self.max_x(), self.max_y()) - } - - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn translate_by_size(&self, size: &TypedSize2D) -> Self { - self.translate(&size.to_vector()) - } - - /// Calculate the size and position of an inner rectangle. - /// - /// Subtracts the side offsets from all sides. The horizontal and vertical - /// offsets must not be larger than the original side length. - pub fn inner_rect(&self, offsets: TypedSideOffsets2D) -> Self { - let rect = TypedRect::new( - TypedPoint2D::new( - self.origin.x + offsets.left, - self.origin.y + offsets.top - ), - TypedSize2D::new( - self.size.width - offsets.horizontal(), - self.size.height - offsets.vertical() - ) - ); - debug_assert!(rect.size.width >= Zero::zero()); - debug_assert!(rect.size.height >= Zero::zero()); - rect - } - - /// Calculate the size and position of an outer rectangle. - /// - /// Add the offsets to all sides. The expanded rectangle is returned. - pub fn outer_rect(&self, offsets: TypedSideOffsets2D) -> Self { - TypedRect::new( - TypedPoint2D::new( - self.origin.x - offsets.left, - self.origin.y - offsets.top - ), - TypedSize2D::new( - self.size.width + offsets.horizontal(), - self.size.height + offsets.vertical() - ) - ) - } - - /// Returns the smallest rectangle defined by the top/bottom/left/right-most - /// points provided as parameter. - /// - /// Note: This function has a behavior that can be surprising because - /// the right-most and bottom-most points are exactly on the edge - /// of the rectangle while the `contains` function is has exclusive - /// semantic on these edges. This means that the right-most and bottom-most - /// points provided to `from_points` will count as not contained by the rect. - /// This behavior may change in the future. - pub fn from_points(points: I) -> Self - where - I: IntoIterator, - I::Item: Borrow>, - { - let mut points = points.into_iter(); - - let (mut min_x, mut min_y) = match points.next() { - Some(first) => (first.borrow().x, first.borrow().y), - None => return TypedRect::zero(), - }; - - let (mut max_x, mut max_y) = (min_x, min_y); - for point in points { - let p = point.borrow(); - if p.x < min_x { - min_x = p.x - } - if p.x > max_x { - max_x = p.x - } - if p.y < min_y { - min_y = p.y - } - if p.y > max_y { - max_y = p.y - } - } - TypedRect::new( - TypedPoint2D::new(min_x, min_y), - TypedSize2D::new(max_x - min_x, max_y - min_y), - ) - } -} - -impl TypedRect -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this rectangle and another rectangle. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - Self::new( - self.origin.lerp(other.origin, t), - self.size.lerp(other.size, t), - ) - } -} - -impl TypedRect -where - T: Copy + Clone + PartialOrd + Add + Sub + Zero, -{ - #[inline] - pub fn union(&self, other: &Self) -> Self { - if self.size == Zero::zero() { - return *other; - } - if other.size == Zero::zero() { - return *self; - } - - let upper_left = TypedPoint2D::new( - min(self.min_x(), other.min_x()), - min(self.min_y(), other.min_y()), - ); - - let lower_right_x = max(self.max_x(), other.max_x()); - let lower_right_y = max(self.max_y(), other.max_y()); - - TypedRect::new( - upper_left, - TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y), - ) - } -} - -impl TypedRect { - #[inline] - pub fn scale(&self, x: S, y: S) -> Self - where - T: Copy + Clone + Mul, - { - TypedRect::new( - TypedPoint2D::new(self.origin.x * x, self.origin.y * y), - TypedSize2D::new(self.size.width * x, self.size.height * y), - ) - } -} - -impl TypedRect { - /// Constructor, setting all sides to zero. - pub fn zero() -> Self { - TypedRect::new(TypedPoint2D::origin(), TypedSize2D::zero()) - } - - /// Returns true if the size is zero, regardless of the origin's value. - pub fn is_empty(&self) -> bool { - self.size.width == Zero::zero() || self.size.height == Zero::zero() - } -} - -pub fn min(x: T, y: T) -> T { - if x <= y { - x - } else { - y - } -} - -pub fn max(x: T, y: T) -> T { - if x >= y { - x - } else { - y - } -} - -impl, U> Mul for TypedRect { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - TypedRect::new(self.origin * scale, self.size * scale) - } -} - -impl, U> Div for TypedRect { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - TypedRect::new(self.origin / scale, self.size / scale) - } -} - -impl, U1, U2> Mul> for TypedRect { - type Output = TypedRect; - #[inline] - fn mul(self, scale: TypedScale) -> TypedRect { - TypedRect::new(self.origin * scale, self.size * scale) - } -} - -impl, U1, U2> Div> for TypedRect { - type Output = TypedRect; - #[inline] - fn div(self, scale: TypedScale) -> TypedRect { - TypedRect::new(self.origin / scale, self.size / scale) - } -} - -impl TypedRect { - /// Drop the units, preserving only the numeric value. - pub fn to_untyped(&self) -> Rect { - TypedRect::new(self.origin.to_untyped(), self.size.to_untyped()) - } - - /// Tag a unitless value with units. - pub fn from_untyped(r: &Rect) -> TypedRect { - TypedRect::new( - TypedPoint2D::from_untyped(&r.origin), - TypedSize2D::from_untyped(&r.size), - ) - } -} - -impl TypedRect { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating point to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using round(), round_in or round_out() before casting. - pub fn cast(&self) -> Option> { - match (self.origin.cast(), self.size.cast()) { - (Some(origin), Some(size)) => Some(TypedRect::new(origin, size)), - _ => None, - } - } -} - -impl + Sub, U> TypedRect { - /// Return a rectangle with edges rounded to integer coordinates, such that - /// the returned rectangle has the same set of pixel centers as the original - /// one. - /// Edges at offset 0.5 round up. - /// Suitable for most places where integral device coordinates - /// are needed, but note that any translation should be applied first to - /// avoid pixel rounding errors. - /// Note that this is *not* rounding to nearest integer if the values are negative. - /// They are always rounding as floor(n + 0.5). - #[cfg_attr(feature = "unstable", must_use)] - pub fn round(&self) -> Self { - let origin = self.origin.round(); - let size = self.origin.add_size(&self.size).round() - origin; - TypedRect::new(origin, TypedSize2D::new(size.x, size.y)) - } - - /// Return a rectangle with edges rounded to integer coordinates, such that - /// the original rectangle contains the resulting rectangle. - #[cfg_attr(feature = "unstable", must_use)] - pub fn round_in(&self) -> Self { - let origin = self.origin.ceil(); - let size = self.origin.add_size(&self.size).floor() - origin; - TypedRect::new(origin, TypedSize2D::new(size.x, size.y)) - } - - /// Return a rectangle with edges rounded to integer coordinates, such that - /// the original rectangle is contained in the resulting rectangle. - #[cfg_attr(feature = "unstable", must_use)] - pub fn round_out(&self) -> Self { - let origin = self.origin.floor(); - let size = self.origin.add_size(&self.size).ceil() - origin; - TypedRect::new(origin, TypedSize2D::new(size.x, size.y)) - } -} - -// Convenience functions for common casts -impl TypedRect { - /// Cast into an `f32` rectangle. - pub fn to_f32(&self) -> TypedRect { - self.cast().unwrap() - } - - /// Cast into an `f64` rectangle. - pub fn to_f64(&self) -> TypedRect { - self.cast().unwrap() - } - - /// Cast into an `usize` rectangle, truncating decimals if any. - /// - /// When casting from floating point rectangles, it is worth considering whether - /// to `round()`, `round_in()` or `round_out()` before the cast in order to - /// obtain the desired conversion behavior. - pub fn to_usize(&self) -> TypedRect { - self.cast().unwrap() - } - - /// Cast into an `u32` rectangle, truncating decimals if any. - /// - /// When casting from floating point rectangles, it is worth considering whether - /// to `round()`, `round_in()` or `round_out()` before the cast in order to - /// obtain the desired conversion behavior. - pub fn to_u32(&self) -> TypedRect { - self.cast().unwrap() - } - - /// Cast into an `i32` rectangle, truncating decimals if any. - /// - /// When casting from floating point rectangles, it is worth considering whether - /// to `round()`, `round_in()` or `round_out()` before the cast in order to - /// obtain the desired conversion behavior. - pub fn to_i32(&self) -> TypedRect { - self.cast().unwrap() - } - - /// Cast into an `i64` rectangle, truncating decimals if any. - /// - /// When casting from floating point rectangles, it is worth considering whether - /// to `round()`, `round_in()` or `round_out()` before the cast in order to - /// obtain the desired conversion behavior. - pub fn to_i64(&self) -> TypedRect { - self.cast().unwrap() - } -} - -/// Shorthand for `TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))`. -pub fn rect(x: T, y: T, w: T, h: T) -> TypedRect { - TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h)) -} - -#[cfg(test)] -mod tests { - use point::Point2D; - use vector::vec2; - use side_offsets::SideOffsets2D; - use size::Size2D; - use super::*; - - #[test] - fn test_min_max() { - assert!(min(0u32, 1u32) == 0u32); - assert!(min(-1.0f32, 0.0f32) == -1.0f32); - - assert!(max(0u32, 1u32) == 1u32); - assert!(max(-1.0f32, 0.0f32) == 0.0f32); - } - - #[test] - fn test_translate() { - let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - let pp = p.translate(&vec2(10, 15)); - - assert!(pp.size.width == 50); - assert!(pp.size.height == 40); - assert!(pp.origin.x == 10); - assert!(pp.origin.y == 15); - - let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - let rr = r.translate(&vec2(0, -10)); - - assert!(rr.size.width == 50); - assert!(rr.size.height == 40); - assert!(rr.origin.x == -10); - assert!(rr.origin.y == -15); - } - - #[test] - fn test_translate_by_size() { - let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - let pp = p.translate_by_size(&Size2D::new(10, 15)); - - assert!(pp.size.width == 50); - assert!(pp.size.height == 40); - assert!(pp.origin.x == 10); - assert!(pp.origin.y == 15); - - let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - let rr = r.translate_by_size(&Size2D::new(0, -10)); - - assert!(rr.size.width == 50); - assert!(rr.size.height == 40); - assert!(rr.origin.x == -10); - assert!(rr.origin.y == -15); - } - - #[test] - fn test_union() { - let p = Rect::new(Point2D::new(0, 0), Size2D::new(50, 40)); - let q = Rect::new(Point2D::new(20, 20), Size2D::new(5, 5)); - let r = Rect::new(Point2D::new(-15, -30), Size2D::new(200, 15)); - let s = Rect::new(Point2D::new(20, -15), Size2D::new(250, 200)); - - let pq = p.union(&q); - assert!(pq.origin == Point2D::new(0, 0)); - assert!(pq.size == Size2D::new(50, 40)); - - let pr = p.union(&r); - assert!(pr.origin == Point2D::new(-15, -30)); - assert!(pr.size == Size2D::new(200, 70)); - - let ps = p.union(&s); - assert!(ps.origin == Point2D::new(0, -15)); - assert!(ps.size == Size2D::new(270, 200)); - } - - #[test] - fn test_intersection() { - let p = Rect::new(Point2D::new(0, 0), Size2D::new(10, 20)); - let q = Rect::new(Point2D::new(5, 15), Size2D::new(10, 10)); - let r = Rect::new(Point2D::new(-5, -5), Size2D::new(8, 8)); - - let pq = p.intersection(&q); - assert!(pq.is_some()); - let pq = pq.unwrap(); - assert!(pq.origin == Point2D::new(5, 15)); - assert!(pq.size == Size2D::new(5, 5)); - - let pr = p.intersection(&r); - assert!(pr.is_some()); - let pr = pr.unwrap(); - assert!(pr.origin == Point2D::new(0, 0)); - assert!(pr.size == Size2D::new(3, 3)); - - let qr = q.intersection(&r); - assert!(qr.is_none()); - } - - #[test] - fn test_contains() { - let r = Rect::new(Point2D::new(-20, 15), Size2D::new(100, 200)); - - assert!(r.contains(&Point2D::new(0, 50))); - assert!(r.contains(&Point2D::new(-10, 200))); - - // The `contains` method is inclusive of the top/left edges, but not the - // bottom/right edges. - assert!(r.contains(&Point2D::new(-20, 15))); - assert!(!r.contains(&Point2D::new(80, 15))); - assert!(!r.contains(&Point2D::new(80, 215))); - assert!(!r.contains(&Point2D::new(-20, 215))); - - // Points beyond the top-left corner. - assert!(!r.contains(&Point2D::new(-25, 15))); - assert!(!r.contains(&Point2D::new(-15, 10))); - - // Points beyond the top-right corner. - assert!(!r.contains(&Point2D::new(85, 20))); - assert!(!r.contains(&Point2D::new(75, 10))); - - // Points beyond the bottom-right corner. - assert!(!r.contains(&Point2D::new(85, 210))); - assert!(!r.contains(&Point2D::new(75, 220))); - - // Points beyond the bottom-left corner. - assert!(!r.contains(&Point2D::new(-25, 210))); - assert!(!r.contains(&Point2D::new(-15, 220))); - - let r = Rect::new(Point2D::new(-20.0, 15.0), Size2D::new(100.0, 200.0)); - assert!(r.contains_rect(&r)); - assert!(!r.contains_rect(&r.translate(&vec2(0.1, 0.0)))); - assert!(!r.contains_rect(&r.translate(&vec2(-0.1, 0.0)))); - assert!(!r.contains_rect(&r.translate(&vec2(0.0, 0.1)))); - assert!(!r.contains_rect(&r.translate(&vec2(0.0, -0.1)))); - // Empty rectangles are always considered as contained in other rectangles, - // even if their origin is not. - let p = Point2D::new(1.0, 1.0); - assert!(!r.contains(&p)); - assert!(r.contains_rect(&Rect::new(p, Size2D::zero()))); - } - - #[test] - fn test_scale() { - let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - let pp = p.scale(10, 15); - - assert!(pp.size.width == 500); - assert!(pp.size.height == 600); - assert!(pp.origin.x == 0); - assert!(pp.origin.y == 0); - - let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - let rr = r.scale(1, 20); - - assert!(rr.size.width == 50); - assert!(rr.size.height == 800); - assert!(rr.origin.x == -10); - assert!(rr.origin.y == -100); - } - - #[test] - fn test_inflate() { - let p = Rect::new(Point2D::new(0, 0), Size2D::new(10, 10)); - let pp = p.inflate(10, 20); - - assert!(pp.size.width == 30); - assert!(pp.size.height == 50); - assert!(pp.origin.x == -10); - assert!(pp.origin.y == -20); - - let r = Rect::new(Point2D::new(0, 0), Size2D::new(10, 20)); - let rr = r.inflate(-2, -5); - - assert!(rr.size.width == 6); - assert!(rr.size.height == 10); - assert!(rr.origin.x == 2); - assert!(rr.origin.y == 5); - } - - #[test] - fn test_inner_outer_rect() { - let inner_rect: Rect = Rect::new(Point2D::new(20, 40), Size2D::new(80, 100)); - let offsets = SideOffsets2D::new(20, 10, 10, 10); - let outer_rect = inner_rect.outer_rect(offsets); - assert_eq!(outer_rect.origin.x, 10); - assert_eq!(outer_rect.origin.y, 20); - assert_eq!(outer_rect.size.width, 100); - assert_eq!(outer_rect.size.height, 130); - assert_eq!(outer_rect.inner_rect(offsets), inner_rect); - } - - #[test] - fn test_min_max_x_y() { - let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32)); - assert!(p.max_y() == 40); - assert!(p.min_y() == 0); - assert!(p.max_x() == 50); - assert!(p.min_x() == 0); - - let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40)); - assert!(r.max_y() == 35); - assert!(r.min_y() == -5); - assert!(r.max_x() == 40); - assert!(r.min_x() == -10); - } - - #[test] - fn test_is_empty() { - assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(0u32, 0u32)).is_empty()); - assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(10u32, 0u32)).is_empty()); - assert!(Rect::new(Point2D::new(0u32, 0u32), Size2D::new(0u32, 10u32)).is_empty()); - assert!(!Rect::new(Point2D::new(0u32, 0u32), Size2D::new(1u32, 1u32)).is_empty()); - assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(0u32, 0u32)).is_empty()); - assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(10u32, 0u32)).is_empty()); - assert!(Rect::new(Point2D::new(10u32, 10u32), Size2D::new(0u32, 10u32)).is_empty()); - assert!(!Rect::new(Point2D::new(10u32, 10u32), Size2D::new(1u32, 1u32)).is_empty()); - } - - #[test] - fn test_round() { - let mut x = -2.0; - let mut y = -2.0; - let mut w = -2.0; - let mut h = -2.0; - while x < 2.0 { - while y < 2.0 { - while w < 2.0 { - while h < 2.0 { - let rect = Rect::new(Point2D::new(x, y), Size2D::new(w, h)); - - assert!(rect.contains_rect(&rect.round_in())); - assert!(rect.round_in().inflate(1.0, 1.0).contains_rect(&rect)); - - assert!(rect.round_out().contains_rect(&rect)); - assert!(rect.inflate(1.0, 1.0).contains_rect(&rect.round_out())); - - assert!(rect.inflate(1.0, 1.0).contains_rect(&rect.round())); - assert!(rect.round().inflate(1.0, 1.0).contains_rect(&rect)); - - h += 0.1; - } - w += 0.1; - } - y += 0.1; - } - x += 0.1 - } - } -} diff --git a/third_party/rust/euclid-0.17.3/src/rotation.rs b/third_party/rust/euclid-0.17.3/src/rotation.rs deleted file mode 100644 index 70e62783c04a..000000000000 --- a/third_party/rust/euclid-0.17.3/src/rotation.rs +++ /dev/null @@ -1,1057 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use approxeq::ApproxEq; -use num_traits::{Float, FloatConst, One, Zero}; -use std::fmt; -use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign}; -use std::marker::PhantomData; -use trig::Trig; -use {TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, Vector3D, point2, point3, vec3}; -use {TypedTransform2D, TypedTransform3D, UnknownUnit}; - -/// An angle in radians -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Angle { - pub radians: T, -} - -impl Angle { - #[inline] - pub fn radians(radians: T) -> Self { - Angle { radians } - } - - #[inline] - pub fn get(self) -> T { - self.radians - } -} - -impl Angle -where - T: Trig, -{ - #[inline] - pub fn degrees(deg: T) -> Self { - Angle { - radians: T::degrees_to_radians(deg), - } - } - - #[inline] - pub fn to_degrees(self) -> T { - T::radians_to_degrees(self.radians) - } -} - -impl Angle -where - T: Rem + Sub + Add + Zero + FloatConst + PartialOrd + Copy, -{ - /// Returns this angle in the [0..2*PI[ range. - pub fn positive(&self) -> Self { - let two_pi = T::PI() + T::PI(); - let mut a = self.radians % two_pi; - if a < T::zero() { - a = a + two_pi; - } - Angle::radians(a) - } - - /// Returns this angle in the ]-PI..PI] range. - pub fn signed(&self) -> Self { - Angle::pi() - (Angle::pi() - *self).positive() - } -} - -impl Angle -where - T: Float, -{ - /// Returns (sin(self), cos(self)). - pub fn sin_cos(self) -> (T, T) { - self.radians.sin_cos() - } -} - -impl Angle -where - T: Zero, -{ - pub fn zero() -> Self { - Angle::radians(T::zero()) - } -} - -impl Angle -where - T: FloatConst + Add, -{ - pub fn pi() -> Self { - Angle::radians(T::PI()) - } - - pub fn two_pi() -> Self { - Angle::radians(T::PI() + T::PI()) - } - - pub fn frac_pi_2() -> Self { - Angle::radians(T::FRAC_PI_2()) - } - - pub fn frac_pi_3() -> Self { - Angle::radians(T::FRAC_PI_3()) - } - - pub fn frac_pi_4() -> Self { - Angle::radians(T::FRAC_PI_4()) - } -} - -impl> Add for Angle { - type Output = Angle; - fn add(self, other: Angle) -> Angle { - Angle::radians(self.radians + other.radians) - } -} - -impl> AddAssign for Angle { - fn add_assign(&mut self, other: Angle) { - self.radians += other.radians; - } -} - -impl> Sub> for Angle { - type Output = Angle; - fn sub(self, other: Angle) -> ::Output { - Angle::radians(self.radians - other.radians) - } -} - -impl> SubAssign for Angle { - fn sub_assign(&mut self, other: Angle) { - self.radians -= other.radians; - } -} - -impl> Div> for Angle { - type Output = T; - #[inline] - fn div(self, other: Angle) -> T { - self.radians / other.radians - } -} - -impl> Div for Angle { - type Output = Angle; - #[inline] - fn div(self, factor: T) -> Angle { - Angle::radians(self.radians / factor) - } -} - -impl> DivAssign for Angle { - fn div_assign(&mut self, factor: T) { - self.radians /= factor; - } -} - -impl> Mul for Angle { - type Output = Angle; - #[inline] - fn mul(self, factor: T) -> Angle { - Angle::radians(self.radians * factor) - } -} - -impl> MulAssign for Angle { - fn mul_assign(&mut self, factor: T) { - self.radians *= factor; - } -} - -impl> Neg for Angle { - type Output = Self; - fn neg(self) -> Self { - Angle::radians(-self.radians) - } -} - -define_matrix! { - /// A transform that can represent rotations in 2d, represented as an angle in radians. - pub struct TypedRotation2D { - pub angle : T, - } -} - -/// The default 2d rotation type with no units. -pub type Rotation2D = TypedRotation2D; - -impl TypedRotation2D { - #[inline] - /// Creates a rotation from an angle in radians. - pub fn new(angle: Angle) -> Self { - TypedRotation2D { - angle: angle.radians, - _unit: PhantomData, - } - } - - pub fn radians(angle: T) -> Self { - Self::new(Angle::radians(angle)) - } - - /// Creates the identity rotation. - #[inline] - pub fn identity() -> Self - where - T: Zero, - { - Self::radians(T::zero()) - } -} - -impl TypedRotation2D -where - T: Clone, -{ - /// Returns self.angle as a strongly typed `Angle`. - pub fn get_angle(&self) -> Angle { - Angle::radians(self.angle.clone()) - } -} - -impl TypedRotation2D -where - T: Copy - + Clone - + Add - + Sub - + Mul - + Div - + Neg - + PartialOrd - + Float - + One - + Zero, -{ - /// Creates a 3d rotation (around the z axis) from this 2d rotation. - #[inline] - pub fn to_3d(&self) -> TypedRotation3D { - TypedRotation3D::around_z(self.get_angle()) - } - - /// Returns the inverse of this rotation. - #[inline] - pub fn inverse(&self) -> TypedRotation2D { - TypedRotation2D::radians(-self.angle) - } - - /// Returns a rotation representing the other rotation followed by this rotation. - #[inline] - pub fn pre_rotate( - &self, - other: &TypedRotation2D, - ) -> TypedRotation2D { - TypedRotation2D::radians(self.angle + other.angle) - } - - /// Returns a rotation representing this rotation followed by the other rotation. - #[inline] - pub fn post_rotate( - &self, - other: &TypedRotation2D, - ) -> TypedRotation2D { - other.pre_rotate(self) - } - - /// Returns the given 2d point transformed by this rotation. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_point(&self, point: &TypedPoint2D) -> TypedPoint2D { - let (sin, cos) = Float::sin_cos(self.angle); - point2(point.x * cos - point.y * sin, point.y * cos + point.x * sin) - } - - /// Returns the given 2d vector transformed by this rotation. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_vector(&self, vector: &TypedVector2D) -> TypedVector2D { - self.transform_point(&vector.to_point()).to_vector() - } -} - -impl TypedRotation2D -where - T: Copy - + Clone - + Add - + Mul - + Div - + Sub - + Trig - + PartialOrd - + One - + Zero, -{ - /// Returns the matrix representation of this rotation. - #[inline] - pub fn to_transform(&self) -> TypedTransform2D { - TypedTransform2D::create_rotation(self.get_angle()) - } -} - -define_matrix! { - /// A transform that can represent rotations in 3d, represented as a quaternion. - /// - /// Most methods expect the quaternion to be normalized. - /// When in doubt, use `unit_quaternion` instead of `quaternion` to create - /// a rotation as the former will ensure that its result is normalized. - /// - /// Some people use the `x, y, z, w` (or `w, x, y, z`) notations. The equivalence is - /// as follows: `x -> i`, `y -> j`, `z -> k`, `w -> r`. - /// The memory layout of this type corresponds to the `x, y, z, w` notation - pub struct TypedRotation3D { - // Component multiplied by the imaginary number `i`. - pub i: T, - // Component multiplied by the imaginary number `j`. - pub j: T, - // Component multiplied by the imaginary number `k`. - pub k: T, - // The real part. - pub r: T, - } -} - -/// The default 3d rotation type with no units. -pub type Rotation3D = TypedRotation3D; - -impl TypedRotation3D { - /// Creates a rotation around from a quaternion representation. - /// - /// The parameters are a, b, c and r compose the quaternion `a*i + b*j + c*k + r` - /// where `a`, `b` and `c` describe the vector part and the last parameter `r` is - /// the real part. - /// - /// The resulting quaternion is not necessarily normalized. See `unit_quaternion`. - #[inline] - pub fn quaternion(a: T, b: T, c: T, r: T) -> Self { - TypedRotation3D { - i: a, - j: b, - k: c, - r, - _unit: PhantomData, - } - } -} - -impl TypedRotation3D -where - T: Copy, -{ - /// Returns the vector part (i, j, k) of this quaternion. - #[inline] - pub fn vector_part(&self) -> Vector3D { - vec3(self.i, self.j, self.k) - } -} - -impl TypedRotation3D -where - T: Float, -{ - /// Creates the identity rotation. - #[inline] - pub fn identity() -> Self { - let zero = T::zero(); - let one = T::one(); - Self::quaternion(zero, zero, zero, one) - } - - /// Creates a rotation around from a quaternion representation and normalizes it. - /// - /// The parameters are a, b, c and r compose the quaternion `a*i + b*j + c*k + r` - /// before normalization, where `a`, `b` and `c` describe the vector part and the - /// last parameter `r` is the real part. - #[inline] - pub fn unit_quaternion(i: T, j: T, k: T, r: T) -> Self { - Self::quaternion(i, j, k, r).normalize() - } - - /// Creates a rotation around a given axis. - pub fn around_axis(axis: TypedVector3D, angle: Angle) -> Self { - let axis = axis.normalize(); - let two = T::one() + T::one(); - let (sin, cos) = Angle::sin_cos(angle / two); - Self::quaternion(axis.x * sin, axis.y * sin, axis.z * sin, cos) - } - - /// Creates a rotation around the x axis. - pub fn around_x(angle: Angle) -> Self { - let zero = Zero::zero(); - let two = T::one() + T::one(); - let (sin, cos) = Angle::sin_cos(angle / two); - Self::quaternion(sin, zero, zero, cos) - } - - /// Creates a rotation around the y axis. - pub fn around_y(angle: Angle) -> Self { - let zero = Zero::zero(); - let two = T::one() + T::one(); - let (sin, cos) = Angle::sin_cos(angle / two); - Self::quaternion(zero, sin, zero, cos) - } - - /// Creates a rotation around the z axis. - pub fn around_z(angle: Angle) -> Self { - let zero = Zero::zero(); - let two = T::one() + T::one(); - let (sin, cos) = Angle::sin_cos(angle / two); - Self::quaternion(zero, zero, sin, cos) - } - - /// Creates a rotation from Euler angles. - /// - /// The rotations are applied in roll then pitch then yaw order. - /// - /// - Roll (also called bank) is a rotation around the x axis. - /// - Pitch (also called bearing) is a rotation around the y axis. - /// - Yaw (also called heading) is a rotation around the z axis. - pub fn euler(roll: Angle, pitch: Angle, yaw: Angle) -> Self { - let half = T::one() / (T::one() + T::one()); - - let (sy, cy) = Float::sin_cos(half * yaw.get()); - let (sp, cp) = Float::sin_cos(half * pitch.get()); - let (sr, cr) = Float::sin_cos(half * roll.get()); - - Self::quaternion( - cy * sr * cp - sy * cr * sp, - cy * cr * sp + sy * sr * cp, - sy * cr * cp - cy * sr * sp, - cy * cr * cp + sy * sr * sp, - ) - } - - /// Returns the inverse of this rotation. - #[inline] - pub fn inverse(&self) -> TypedRotation3D { - TypedRotation3D::quaternion(-self.i, -self.j, -self.k, self.r) - } - - /// Computes the norm of this quaternion - #[inline] - pub fn norm(&self) -> T { - self.square_norm().sqrt() - } - - #[inline] - pub fn square_norm(&self) -> T { - (self.i * self.i + self.j * self.j + self.k * self.k + self.r * self.r) - } - - /// Returns a unit quaternion from this one. - #[inline] - pub fn normalize(&self) -> Self { - self.mul(T::one() / self.norm()) - } - - #[inline] - pub fn is_normalized(&self) -> bool - where - T: ApproxEq, - { - // TODO: we might need to relax the threshold here, because of floating point imprecision. - self.square_norm().approx_eq(&T::one()) - } - - /// Spherical linear interpolation between this rotation and another rotation. - /// - /// `t` is expected to be between zero and one. - pub fn slerp(&self, other: &Self, t: T) -> Self - where - T: ApproxEq, - { - debug_assert!(self.is_normalized()); - debug_assert!(other.is_normalized()); - - let r1 = *self; - let mut r2 = *other; - - let mut dot = r1.i * r2.i + r1.j * r2.j + r1.k * r2.k + r1.r * r2.r; - - let one = T::one(); - - if dot.approx_eq(&T::one()) { - // If the inputs are too close, linearly interpolate to avoid precision issues. - return r1.lerp(&r2, t); - } - - // If the dot product is negative, the quaternions - // have opposite handed-ness and slerp won't take - // the shorter path. Fix by reversing one quaternion. - if dot < T::zero() { - r2 = r2.mul(-T::one()); - dot = -dot; - } - - // For robustness, stay within the domain of acos. - dot = Float::min(dot, one); - - // Angle between r1 and the result. - let theta = Float::acos(dot) * t; - - // r1 and r3 form an orthonormal basis. - let r3 = r2.sub(r1.mul(dot)).normalize(); - let (sin, cos) = Float::sin_cos(theta); - r1.mul(cos).add(r3.mul(sin)) - } - - /// Basic Linear interpolation between this rotation and another rotation. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: &Self, t: T) -> Self { - let one_t = T::one() - t; - self.mul(one_t).add(other.mul(t)).normalize() - } - - /// Returns the given 3d point transformed by this rotation. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - pub fn rotate_point3d(&self, point: &TypedPoint3D) -> TypedPoint3D - where - T: ApproxEq, - { - debug_assert!(self.is_normalized()); - - let two = T::one() + T::one(); - let cross = self.vector_part().cross(point.to_vector().to_untyped()) * two; - - point3( - point.x + self.r * cross.x + self.j * cross.z - self.k * cross.y, - point.y + self.r * cross.y + self.k * cross.x - self.i * cross.z, - point.z + self.r * cross.z + self.i * cross.y - self.j * cross.x, - ) - } - - /// Returns the given 2d point transformed by this rotation then projected on the xy plane. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn rotate_point2d(&self, point: &TypedPoint2D) -> TypedPoint2D - where - T: ApproxEq, - { - self.rotate_point3d(&point.to_3d()).xy() - } - - /// Returns the given 3d vector transformed by this rotation then projected on the xy plane. - /// - /// The input vector must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn rotate_vector3d(&self, vector: &TypedVector3D) -> TypedVector3D - where - T: ApproxEq, - { - self.rotate_point3d(&vector.to_point()).to_vector() - } - - /// Returns the given 2d vector transformed by this rotation then projected on the xy plane. - /// - /// The input vector must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn rotate_vector2d(&self, vector: &TypedVector2D) -> TypedVector2D - where - T: ApproxEq, - { - self.rotate_vector3d(&vector.to_3d()).xy() - } - - /// Returns the matrix representation of this rotation. - #[inline] - pub fn to_transform(&self) -> TypedTransform3D - where - T: ApproxEq, - { - debug_assert!(self.is_normalized()); - - let i2 = self.i + self.i; - let j2 = self.j + self.j; - let k2 = self.k + self.k; - let ii = self.i * i2; - let ij = self.i * j2; - let ik = self.i * k2; - let jj = self.j * j2; - let jk = self.j * k2; - let kk = self.k * k2; - let ri = self.r * i2; - let rj = self.r * j2; - let rk = self.r * k2; - - let one = T::one(); - let zero = T::zero(); - - let m11 = one - (jj + kk); - let m12 = ij + rk; - let m13 = ik - rj; - - let m21 = ij - rk; - let m22 = one - (ii + kk); - let m23 = jk + ri; - - let m31 = ik + rj; - let m32 = jk - ri; - let m33 = one - (ii + jj); - - TypedTransform3D::row_major( - m11, - m12, - m13, - zero, - m21, - m22, - m23, - zero, - m31, - m32, - m33, - zero, - zero, - zero, - zero, - one, - ) - } - - /// Returns a rotation representing the other rotation followed by this rotation. - pub fn pre_rotate( - &self, - other: &TypedRotation3D, - ) -> TypedRotation3D - where - T: ApproxEq, - { - debug_assert!(self.is_normalized()); - TypedRotation3D::quaternion( - self.i * other.r + self.r * other.i + self.j * other.k - self.k * other.j, - self.j * other.r + self.r * other.j + self.k * other.i - self.i * other.k, - self.k * other.r + self.r * other.k + self.i * other.j - self.j * other.i, - self.r * other.r - self.i * other.i - self.j * other.j - self.k * other.k, - ) - } - - /// Returns a rotation representing this rotation followed by the other rotation. - #[inline] - pub fn post_rotate( - &self, - other: &TypedRotation3D, - ) -> TypedRotation3D - where - T: ApproxEq, - { - other.pre_rotate(self) - } - - // add, sub and mul are used internally for intermediate computation but aren't public - // because they don't carry real semantic meanings (I think?). - - #[inline] - fn add(&self, other: Self) -> Self { - Self::quaternion( - self.i + other.i, - self.j + other.j, - self.k + other.k, - self.r + other.r, - ) - } - - #[inline] - fn sub(&self, other: Self) -> Self { - Self::quaternion( - self.i - other.i, - self.j - other.j, - self.k - other.k, - self.r - other.r, - ) - } - - #[inline] - fn mul(&self, factor: T) -> Self { - Self::quaternion( - self.i * factor, - self.j * factor, - self.k * factor, - self.r * factor, - ) - } -} - -impl fmt::Debug for TypedRotation3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Quat({:?}*i + {:?}*j + {:?}*k + {:?})", - self.i, self.j, self.k, self.r - ) - } -} - -impl fmt::Display for TypedRotation3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Quat({}*i + {}*j + {}*k + {})", - self.i, self.j, self.k, self.r - ) - } -} - -impl ApproxEq for TypedRotation3D -where - T: Copy + Neg + ApproxEq, -{ - fn approx_epsilon() -> T { - T::approx_epsilon() - } - - fn approx_eq(&self, other: &Self) -> bool { - self.approx_eq_eps(other, &Self::approx_epsilon()) - } - - fn approx_eq_eps(&self, other: &Self, eps: &T) -> bool { - (self.i.approx_eq_eps(&other.i, eps) && self.j.approx_eq_eps(&other.j, eps) - && self.k.approx_eq_eps(&other.k, eps) && self.r.approx_eq_eps(&other.r, eps)) - || (self.i.approx_eq_eps(&-other.i, eps) && self.j.approx_eq_eps(&-other.j, eps) - && self.k.approx_eq_eps(&-other.k, eps) - && self.r.approx_eq_eps(&-other.r, eps)) - } -} - -#[test] -fn simple_rotation_2d() { - use std::f32::consts::{FRAC_PI_2, PI}; - let ri = Rotation2D::identity(); - let r90 = Rotation2D::radians(FRAC_PI_2); - let rm90 = Rotation2D::radians(-FRAC_PI_2); - let r180 = Rotation2D::radians(PI); - - assert!( - ri.transform_point(&point2(1.0, 2.0)) - .approx_eq(&point2(1.0, 2.0)) - ); - assert!( - r90.transform_point(&point2(1.0, 2.0)) - .approx_eq(&point2(-2.0, 1.0)) - ); - assert!( - rm90.transform_point(&point2(1.0, 2.0)) - .approx_eq(&point2(2.0, -1.0)) - ); - assert!( - r180.transform_point(&point2(1.0, 2.0)) - .approx_eq(&point2(-1.0, -2.0)) - ); - - assert!( - r90.inverse() - .inverse() - .transform_point(&point2(1.0, 2.0)) - .approx_eq(&r90.transform_point(&point2(1.0, 2.0))) - ); -} - -#[test] -fn simple_rotation_3d_in_2d() { - use std::f32::consts::{FRAC_PI_2, PI}; - let ri = Rotation3D::identity(); - let r90 = Rotation3D::around_z(Angle::radians(FRAC_PI_2)); - let rm90 = Rotation3D::around_z(Angle::radians(-FRAC_PI_2)); - let r180 = Rotation3D::around_z(Angle::radians(PI)); - - assert!( - ri.rotate_point2d(&point2(1.0, 2.0)) - .approx_eq(&point2(1.0, 2.0)) - ); - assert!( - r90.rotate_point2d(&point2(1.0, 2.0)) - .approx_eq(&point2(-2.0, 1.0)) - ); - assert!( - rm90.rotate_point2d(&point2(1.0, 2.0)) - .approx_eq(&point2(2.0, -1.0)) - ); - assert!( - r180.rotate_point2d(&point2(1.0, 2.0)) - .approx_eq(&point2(-1.0, -2.0)) - ); - - assert!( - r90.inverse() - .inverse() - .rotate_point2d(&point2(1.0, 2.0)) - .approx_eq(&r90.rotate_point2d(&point2(1.0, 2.0))) - ); -} - -#[test] -fn pre_post() { - use std::f32::consts::FRAC_PI_2; - let r1 = Rotation3D::around_x(Angle::radians(FRAC_PI_2)); - let r2 = Rotation3D::around_y(Angle::radians(FRAC_PI_2)); - let r3 = Rotation3D::around_z(Angle::radians(FRAC_PI_2)); - - let t1 = r1.to_transform(); - let t2 = r2.to_transform(); - let t3 = r3.to_transform(); - - let p = point3(1.0, 2.0, 3.0); - - // Check that the order of transformations is correct (corresponds to what - // we do in Transform3D). - let p1 = r1.post_rotate(&r2).post_rotate(&r3).rotate_point3d(&p); - let p2 = t1.post_mul(&t2).post_mul(&t3).transform_point3d(&p); - - assert!(p1.approx_eq(&p2)); - - // Check that changing the order indeed matters. - let p3 = t3.post_mul(&t1).post_mul(&t2).transform_point3d(&p); - assert!(!p1.approx_eq(&p3)); -} - -#[test] -fn to_transform3d() { - use std::f32::consts::{FRAC_PI_2, PI}; - let rotations = [ - Rotation3D::identity(), - Rotation3D::around_x(Angle::radians(FRAC_PI_2)), - Rotation3D::around_x(Angle::radians(-FRAC_PI_2)), - Rotation3D::around_x(Angle::radians(PI)), - Rotation3D::around_y(Angle::radians(FRAC_PI_2)), - Rotation3D::around_y(Angle::radians(-FRAC_PI_2)), - Rotation3D::around_y(Angle::radians(PI)), - Rotation3D::around_z(Angle::radians(FRAC_PI_2)), - Rotation3D::around_z(Angle::radians(-FRAC_PI_2)), - Rotation3D::around_z(Angle::radians(PI)), - ]; - - let points = [ - point3(0.0, 0.0, 0.0), - point3(1.0, 2.0, 3.0), - point3(-5.0, 3.0, -1.0), - point3(-0.5, -1.0, 1.5), - ]; - - for rotation in &rotations { - for point in &points { - let p1 = rotation.rotate_point3d(point); - let p2 = rotation.to_transform().transform_point3d(point); - assert!(p1.approx_eq(&p2)); - } - } -} - -#[test] -fn slerp() { - let q1 = Rotation3D::quaternion(1.0, 0.0, 0.0, 0.0); - let q2 = Rotation3D::quaternion(0.0, 1.0, 0.0, 0.0); - let q3 = Rotation3D::quaternion(0.0, 0.0, -1.0, 0.0); - - // The values below can be obtained with a python program: - // import numpy - // import quaternion - // q1 = numpy.quaternion(1, 0, 0, 0) - // q2 = numpy.quaternion(0, 1, 0, 0) - // quaternion.slerp_evaluate(q1, q2, 0.2) - - assert!(q1.slerp(&q2, 0.0).approx_eq(&q1)); - assert!(q1.slerp(&q2, 0.2).approx_eq(&Rotation3D::quaternion( - 0.951056516295154, - 0.309016994374947, - 0.0, - 0.0 - ))); - assert!(q1.slerp(&q2, 0.4).approx_eq(&Rotation3D::quaternion( - 0.809016994374947, - 0.587785252292473, - 0.0, - 0.0 - ))); - assert!(q1.slerp(&q2, 0.6).approx_eq(&Rotation3D::quaternion( - 0.587785252292473, - 0.809016994374947, - 0.0, - 0.0 - ))); - assert!(q1.slerp(&q2, 0.8).approx_eq(&Rotation3D::quaternion( - 0.309016994374947, - 0.951056516295154, - 0.0, - 0.0 - ))); - assert!(q1.slerp(&q2, 1.0).approx_eq(&q2)); - - assert!(q1.slerp(&q3, 0.0).approx_eq(&q1)); - assert!(q1.slerp(&q3, 0.2).approx_eq(&Rotation3D::quaternion( - 0.951056516295154, - 0.0, - -0.309016994374947, - 0.0 - ))); - assert!(q1.slerp(&q3, 0.4).approx_eq(&Rotation3D::quaternion( - 0.809016994374947, - 0.0, - -0.587785252292473, - 0.0 - ))); - assert!(q1.slerp(&q3, 0.6).approx_eq(&Rotation3D::quaternion( - 0.587785252292473, - 0.0, - -0.809016994374947, - 0.0 - ))); - assert!(q1.slerp(&q3, 0.8).approx_eq(&Rotation3D::quaternion( - 0.309016994374947, - 0.0, - -0.951056516295154, - 0.0 - ))); - assert!(q1.slerp(&q3, 1.0).approx_eq(&q3)); -} - -#[test] -fn around_axis() { - use std::f32::consts::{FRAC_PI_2, PI}; - - // Two sort of trivial cases: - let r1 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(PI)); - let r2 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(FRAC_PI_2)); - assert!( - r1.rotate_point3d(&point3(1.0, 2.0, 0.0)) - .approx_eq(&point3(2.0, 1.0, 0.0)) - ); - assert!( - r2.rotate_point3d(&point3(1.0, 0.0, 0.0)) - .approx_eq(&point3(0.5, 0.5, -0.5.sqrt())) - ); - - // A more arbitrary test (made up with numpy): - let r3 = Rotation3D::around_axis(vec3(0.5, 1.0, 2.0), Angle::radians(2.291288)); - assert!(r3.rotate_point3d(&point3(1.0, 0.0, 0.0)).approx_eq(&point3( - -0.58071821, - 0.81401868, - -0.01182979 - ))); -} - -#[test] -fn from_euler() { - use std::f32::consts::FRAC_PI_2; - - // First test simple separate yaw pitch and roll rotations, because it is easy to come - // up with the corresponding quaternion. - // Since several quaternions can represent the same transformation we compare the result - // of transforming a point rather than the values of each quaternions. - let p = point3(1.0, 2.0, 3.0); - - let angle = Angle::radians(FRAC_PI_2); - let zero = Angle::radians(0.0); - - // roll - let roll_re = Rotation3D::euler(angle, zero, zero); - let roll_rq = Rotation3D::around_x(angle); - let roll_pe = roll_re.rotate_point3d(&p); - let roll_pq = roll_rq.rotate_point3d(&p); - - // pitch - let pitch_re = Rotation3D::euler(zero, angle, zero); - let pitch_rq = Rotation3D::around_y(angle); - let pitch_pe = pitch_re.rotate_point3d(&p); - let pitch_pq = pitch_rq.rotate_point3d(&p); - - // yaw - let yaw_re = Rotation3D::euler(zero, zero, angle); - let yaw_rq = Rotation3D::around_z(angle); - let yaw_pe = yaw_re.rotate_point3d(&p); - let yaw_pq = yaw_rq.rotate_point3d(&p); - - assert!(roll_pe.approx_eq(&roll_pq)); - assert!(pitch_pe.approx_eq(&pitch_pq)); - assert!(yaw_pe.approx_eq(&yaw_pq)); - - // Now check that the yaw pitch and roll transformations when combined are applied in - // the proper order: roll -> pitch -> yaw. - let ypr_e = Rotation3D::euler(angle, angle, angle); - let ypr_q = roll_rq.post_rotate(&pitch_rq).post_rotate(&yaw_rq); - let ypr_pe = ypr_e.rotate_point3d(&p); - let ypr_pq = ypr_q.rotate_point3d(&p); - - assert!(ypr_pe.approx_eq(&ypr_pq)); -} - -#[test] -fn wrap_angles() { - use std::f32::consts::{FRAC_PI_2, PI}; - assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0)); - assert!( - Angle::radians(FRAC_PI_2) - .positive() - .radians - .approx_eq(&FRAC_PI_2) - ); - assert!( - Angle::radians(-FRAC_PI_2) - .positive() - .radians - .approx_eq(&(3.0 * FRAC_PI_2)) - ); - assert!( - Angle::radians(3.0 * FRAC_PI_2) - .positive() - .radians - .approx_eq(&(3.0 * FRAC_PI_2)) - ); - assert!( - Angle::radians(5.0 * FRAC_PI_2) - .positive() - .radians - .approx_eq(&FRAC_PI_2) - ); - assert!(Angle::radians(2.0 * PI).positive().radians.approx_eq(&0.0)); - assert!(Angle::radians(-2.0 * PI).positive().radians.approx_eq(&0.0)); - assert!(Angle::radians(PI).positive().radians.approx_eq(&PI)); - assert!(Angle::radians(-PI).positive().radians.approx_eq(&PI)); - - assert!( - Angle::radians(FRAC_PI_2) - .signed() - .radians - .approx_eq(&FRAC_PI_2) - ); - assert!( - Angle::radians(3.0 * FRAC_PI_2) - .signed() - .radians - .approx_eq(&-FRAC_PI_2) - ); - assert!( - Angle::radians(5.0 * FRAC_PI_2) - .signed() - .radians - .approx_eq(&FRAC_PI_2) - ); - assert!(Angle::radians(2.0 * PI).signed().radians.approx_eq(&0.0)); - assert!(Angle::radians(-2.0 * PI).signed().radians.approx_eq(&0.0)); - assert!(Angle::radians(-PI).signed().radians.approx_eq(&PI)); - assert!(Angle::radians(PI).signed().radians.approx_eq(&PI)); -} diff --git a/third_party/rust/euclid-0.17.3/src/scale.rs b/third_party/rust/euclid-0.17.3/src/scale.rs deleted file mode 100644 index 575bc238107b..000000000000 --- a/third_party/rust/euclid-0.17.3/src/scale.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright 2014 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -//! A type-checked scaling factor between units. - -use num::One; - -use num_traits::NumCast; -#[cfg(feature = "serde")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt; -use std::ops::{Add, Div, Mul, Neg, Sub}; -use std::marker::PhantomData; -use {TypedPoint2D, TypedRect, TypedSize2D, TypedVector2D}; - -/// A scaling factor between two different units of measurement. -/// -/// This is effectively a type-safe float, intended to be used in combination with other types like -/// `length::Length` to enforce conversion between systems of measurement at compile time. -/// -/// `Src` and `Dst` represent the units before and after multiplying a value by a `TypedScale`. They -/// may be types without values, such as empty enums. For example: -/// -/// ```rust -/// use euclid::TypedScale; -/// use euclid::Length; -/// enum Mm {}; -/// enum Inch {}; -/// -/// let mm_per_inch: TypedScale = TypedScale::new(25.4); -/// -/// let one_foot: Length = Length::new(12.0); -/// let one_foot_in_mm: Length = one_foot * mm_per_inch; -/// ``` -#[repr(C)] -pub struct TypedScale(pub T, PhantomData<(Src, Dst)>); - -#[cfg(feature = "serde")] -impl<'de, T, Src, Dst> Deserialize<'de> for TypedScale -where - T: Deserialize<'de>, -{ - fn deserialize(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - Ok(TypedScale( - try!(Deserialize::deserialize(deserializer)), - PhantomData, - )) - } -} - -#[cfg(feature = "serde")] -impl Serialize for TypedScale -where - T: Serialize, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.0.serialize(serializer) - } -} - -impl TypedScale { - pub fn new(x: T) -> Self { - TypedScale(x, PhantomData) - } -} - -impl TypedScale { - pub fn get(&self) -> T { - self.0.clone() - } -} - -impl TypedScale { - /// Identity scaling, could be used to safely transit from one space to another. - pub const ONE: Self = TypedScale(1.0, PhantomData); -} - -impl, Src, Dst> TypedScale { - /// The inverse TypedScale (1.0 / self). - pub fn inv(&self) -> TypedScale { - let one: T = One::one(); - TypedScale::new(one / self.get()) - } -} - -// scale0 * scale1 -impl, A, B, C> Mul> for TypedScale { - type Output = TypedScale; - #[inline] - fn mul(self, other: TypedScale) -> TypedScale { - TypedScale::new(self.get() * other.get()) - } -} - -// scale0 + scale1 -impl, Src, Dst> Add for TypedScale { - type Output = TypedScale; - #[inline] - fn add(self, other: TypedScale) -> TypedScale { - TypedScale::new(self.get() + other.get()) - } -} - -// scale0 - scale1 -impl, Src, Dst> Sub for TypedScale { - type Output = TypedScale; - #[inline] - fn sub(self, other: TypedScale) -> TypedScale { - TypedScale::new(self.get() - other.get()) - } -} - -impl TypedScale { - /// Cast from one numeric representation to another, preserving the units. - pub fn cast(&self) -> Option> { - NumCast::from(self.get()).map(TypedScale::new) - } -} - -impl TypedScale -where - T: Copy + Clone + Mul + Neg + PartialEq + One, -{ - /// Returns the given point transformed by this scale. - #[inline] - pub fn transform_point(&self, point: &TypedPoint2D) -> TypedPoint2D { - TypedPoint2D::new(point.x * self.get(), point.y * self.get()) - } - - /// Returns the given vector transformed by this scale. - #[inline] - pub fn transform_vector(&self, vec: &TypedVector2D) -> TypedVector2D { - TypedVector2D::new(vec.x * self.get(), vec.y * self.get()) - } - - /// Returns the given vector transformed by this scale. - #[inline] - pub fn transform_size(&self, size: &TypedSize2D) -> TypedSize2D { - TypedSize2D::new(size.width * self.get(), size.height * self.get()) - } - - /// Returns the given rect transformed by this scale. - #[inline] - pub fn transform_rect(&self, rect: &TypedRect) -> TypedRect { - TypedRect::new( - self.transform_point(&rect.origin), - self.transform_size(&rect.size), - ) - } - - /// Returns the inverse of this scale. - #[inline] - pub fn inverse(&self) -> TypedScale { - TypedScale::new(-self.get()) - } - - /// Returns true if this scale has no effect. - #[inline] - pub fn is_identity(&self) -> bool { - self.get() == T::one() - } -} - -// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed: -// https://github.com/mozilla/rust/issues/7671 - -impl PartialEq for TypedScale { - fn eq(&self, other: &TypedScale) -> bool { - self.0 == other.0 - } -} - -impl Clone for TypedScale { - fn clone(&self) -> TypedScale { - TypedScale::new(self.get()) - } -} - -impl Copy for TypedScale {} - -impl fmt::Debug for TypedScale { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl fmt::Display for TypedScale { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -#[cfg(test)] -mod tests { - use super::TypedScale; - - enum Inch {} - enum Cm {} - enum Mm {} - - #[test] - fn test_scale() { - let mm_per_inch: TypedScale = TypedScale::new(25.4); - let cm_per_mm: TypedScale = TypedScale::new(0.1); - - let mm_per_cm: TypedScale = cm_per_mm.inv(); - assert_eq!(mm_per_cm.get(), 10.0); - - let cm_per_inch: TypedScale = mm_per_inch * cm_per_mm; - assert_eq!(cm_per_inch, TypedScale::new(2.54)); - - let a: TypedScale = TypedScale::new(2); - let b: TypedScale = TypedScale::new(3); - assert!(a != b); - assert_eq!(a, a.clone()); - assert_eq!(a.clone() + b.clone(), TypedScale::new(5)); - assert_eq!(a - b, TypedScale::new(-1)); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/side_offsets.rs b/third_party/rust/euclid-0.17.3/src/side_offsets.rs deleted file mode 100644 index fc4243713633..000000000000 --- a/third_party/rust/euclid-0.17.3/src/side_offsets.rs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding, -//! and margins in CSS. - -use super::UnknownUnit; -use length::Length; -use num::Zero; -use std::fmt; -use std::ops::Add; -use std::marker::PhantomData; - -/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding, -/// and margins in CSS, optionally tagged with a unit. -define_matrix! { - pub struct TypedSideOffsets2D { - pub top: T, - pub right: T, - pub bottom: T, - pub left: T, - } -} - -impl fmt::Debug for TypedSideOffsets2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "({:?},{:?},{:?},{:?})", - self.top, self.right, self.bottom, self.left - ) - } -} - -/// The default side offset type with no unit. -pub type SideOffsets2D = TypedSideOffsets2D; - -impl TypedSideOffsets2D { - /// Constructor taking a scalar for each side. - pub fn new(top: T, right: T, bottom: T, left: T) -> Self { - TypedSideOffsets2D { - top: top, - right: right, - bottom: bottom, - left: left, - _unit: PhantomData, - } - } - - /// Constructor taking a typed Length for each side. - pub fn from_lengths( - top: Length, - right: Length, - bottom: Length, - left: Length, - ) -> Self { - TypedSideOffsets2D::new(top.0, right.0, bottom.0, left.0) - } - - /// Access self.top as a typed Length instead of a scalar value. - pub fn top_typed(&self) -> Length { - Length::new(self.top) - } - - /// Access self.right as a typed Length instead of a scalar value. - pub fn right_typed(&self) -> Length { - Length::new(self.right) - } - - /// Access self.bottom as a typed Length instead of a scalar value. - pub fn bottom_typed(&self) -> Length { - Length::new(self.bottom) - } - - /// Access self.left as a typed Length instead of a scalar value. - pub fn left_typed(&self) -> Length { - Length::new(self.left) - } - - /// Constructor setting the same value to all sides, taking a scalar value directly. - pub fn new_all_same(all: T) -> Self { - TypedSideOffsets2D::new(all, all, all, all) - } - - /// Constructor setting the same value to all sides, taking a typed Length. - pub fn from_length_all_same(all: Length) -> Self { - TypedSideOffsets2D::new_all_same(all.0) - } -} - -impl TypedSideOffsets2D -where - T: Add + Copy, -{ - pub fn horizontal(&self) -> T { - self.left + self.right - } - - pub fn vertical(&self) -> T { - self.top + self.bottom - } - - pub fn horizontal_typed(&self) -> Length { - Length::new(self.horizontal()) - } - - pub fn vertical_typed(&self) -> Length { - Length::new(self.vertical()) - } -} - -impl Add for TypedSideOffsets2D -where - T: Copy + Add, -{ - type Output = Self; - fn add(self, other: Self) -> Self { - TypedSideOffsets2D::new( - self.top + other.top, - self.right + other.right, - self.bottom + other.bottom, - self.left + other.left, - ) - } -} - -impl TypedSideOffsets2D { - /// Constructor, setting all sides to zero. - pub fn zero() -> Self { - TypedSideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()) - } -} diff --git a/third_party/rust/euclid-0.17.3/src/size.rs b/third_party/rust/euclid-0.17.3/src/size.rs deleted file mode 100644 index b5dd9bcc2ba8..000000000000 --- a/third_party/rust/euclid-0.17.3/src/size.rs +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::UnknownUnit; -use length::Length; -use scale::TypedScale; -use vector::{TypedVector2D, vec2, BoolVector2D}; -use num::*; - -use num_traits::{NumCast, Signed}; -use std::fmt; -use std::ops::{Add, Div, Mul, Sub}; -use std::marker::PhantomData; - -/// A 2d size tagged with a unit. -define_matrix! { - pub struct TypedSize2D { - pub width: T, - pub height: T, - } -} - -/// Default 2d size type with no unit. -/// -/// `Size2D` provides the same methods as `TypedSize2D`. -pub type Size2D = TypedSize2D; - -impl fmt::Debug for TypedSize2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}×{:?}", self.width, self.height) - } -} - -impl fmt::Display for TypedSize2D { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "({}x{})", self.width, self.height) - } -} - -impl TypedSize2D { - /// Constructor taking scalar values. - pub fn new(width: T, height: T) -> Self { - TypedSize2D { - width: width, - height: height, - _unit: PhantomData, - } - } -} - -impl TypedSize2D { - /// Constructor taking scalar strongly typed lengths. - pub fn from_lengths(width: Length, height: Length) -> Self { - TypedSize2D::new(width.get(), height.get()) - } -} - -impl TypedSize2D { - /// Rounds each component to the nearest integer value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - pub fn round(&self) -> Self { - TypedSize2D::new(self.width.round(), self.height.round()) - } -} - -impl TypedSize2D { - /// Rounds each component to the smallest integer equal or greater than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - pub fn ceil(&self) -> Self { - TypedSize2D::new(self.width.ceil(), self.height.ceil()) - } -} - -impl TypedSize2D { - /// Rounds each component to the biggest integer equal or lower than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - pub fn floor(&self) -> Self { - TypedSize2D::new(self.width.floor(), self.height.floor()) - } -} - -impl, U> Add for TypedSize2D { - type Output = Self; - fn add(self, other: Self) -> Self { - TypedSize2D::new(self.width + other.width, self.height + other.height) - } -} - -impl, U> Sub for TypedSize2D { - type Output = Self; - fn sub(self, other: Self) -> Self { - TypedSize2D::new(self.width - other.width, self.height - other.height) - } -} - -impl, U> TypedSize2D { - pub fn area(&self) -> T::Output { - self.width * self.height - } -} - -impl TypedSize2D -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this size and another size. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - size2( - one_t * self.width + t * other.width, - one_t * self.height + t * other.height, - ) - } -} - -impl TypedSize2D { - pub fn is_empty_or_negative(&self) -> bool { - let zero = T::zero(); - self.width <= zero || self.height <= zero - } -} - -impl TypedSize2D { - pub fn zero() -> Self { - TypedSize2D::new(Zero::zero(), Zero::zero()) - } -} - -impl Zero for TypedSize2D { - fn zero() -> Self { - TypedSize2D::new(Zero::zero(), Zero::zero()) - } -} - -impl, U> Mul for TypedSize2D { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - TypedSize2D::new(self.width * scale, self.height * scale) - } -} - -impl, U> Div for TypedSize2D { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - TypedSize2D::new(self.width / scale, self.height / scale) - } -} - -impl, U1, U2> Mul> for TypedSize2D { - type Output = TypedSize2D; - #[inline] - fn mul(self, scale: TypedScale) -> TypedSize2D { - TypedSize2D::new(self.width * scale.get(), self.height * scale.get()) - } -} - -impl, U1, U2> Div> for TypedSize2D { - type Output = TypedSize2D; - #[inline] - fn div(self, scale: TypedScale) -> TypedSize2D { - TypedSize2D::new(self.width / scale.get(), self.height / scale.get()) - } -} - -impl TypedSize2D { - /// Returns self.width as a Length carrying the unit. - #[inline] - pub fn width_typed(&self) -> Length { - Length::new(self.width) - } - - /// Returns self.height as a Length carrying the unit. - #[inline] - pub fn height_typed(&self) -> Length { - Length::new(self.height) - } - - #[inline] - pub fn to_array(&self) -> [T; 2] { - [self.width, self.height] - } - - #[inline] - pub fn to_vector(&self) -> TypedVector2D { - vec2(self.width, self.height) - } - - /// Drop the units, preserving only the numeric value. - pub fn to_untyped(&self) -> Size2D { - TypedSize2D::new(self.width, self.height) - } - - /// Tag a unitless value with units. - pub fn from_untyped(p: &Size2D) -> Self { - TypedSize2D::new(p.width, p.height) - } -} - -impl TypedSize2D { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating point to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. - pub fn cast(&self) -> Option> { - match (NumCast::from(self.width), NumCast::from(self.height)) { - (Some(w), Some(h)) => Some(TypedSize2D::new(w, h)), - _ => None, - } - } - - // Convenience functions for common casts - - /// Cast into an `f32` size. - pub fn to_f32(&self) -> TypedSize2D { - self.cast().unwrap() - } - - /// Cast into an `f64` size. - pub fn to_f64(&self) -> TypedSize2D { - self.cast().unwrap() - } - - /// Cast into an `uint` size, truncating decimals if any. - /// - /// When casting from floating point sizes, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - pub fn to_usize(&self) -> TypedSize2D { - self.cast().unwrap() - } - - /// Cast into an `u32` size, truncating decimals if any. - /// - /// When casting from floating point sizes, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - pub fn to_u32(&self) -> TypedSize2D { - self.cast().unwrap() - } - - /// Cast into an `i32` size, truncating decimals if any. - /// - /// When casting from floating point sizes, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - pub fn to_i32(&self) -> TypedSize2D { - self.cast().unwrap() - } - - /// Cast into an `i64` size, truncating decimals if any. - /// - /// When casting from floating point sizes, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - pub fn to_i64(&self) -> TypedSize2D { - self.cast().unwrap() - } -} - -impl TypedSize2D -where - T: Signed, -{ - pub fn abs(&self) -> Self { - size2(self.width.abs(), self.height.abs()) - } - - pub fn is_positive(&self) -> bool { - self.width.is_positive() && self.height.is_positive() - } -} - -impl TypedSize2D { - pub fn greater_than(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.width > other.width, - y: self.height > other.height, - } - } - - pub fn lower_than(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.width < other.width, - y: self.height < other.height, - } - } -} - - -impl TypedSize2D { - pub fn equal(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.width == other.width, - y: self.height == other.height, - } - } - - pub fn not_equal(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.width != other.width, - y: self.height != other.height, - } - } -} - -/// Shorthand for `TypedSize2D::new(w, h)`. -pub fn size2(w: T, h: T) -> TypedSize2D { - TypedSize2D::new(w, h) -} - -#[cfg(test)] -mod size2d { - use super::Size2D; - - #[test] - pub fn test_add() { - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(3.0, 4.0); - assert_eq!(p1 + p2, Size2D::new(4.0, 6.0)); - - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(0.0, 0.0); - assert_eq!(p1 + p2, Size2D::new(1.0, 2.0)); - - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(-3.0, -4.0); - assert_eq!(p1 + p2, Size2D::new(-2.0, -2.0)); - - let p1 = Size2D::new(0.0, 0.0); - let p2 = Size2D::new(0.0, 0.0); - assert_eq!(p1 + p2, Size2D::new(0.0, 0.0)); - } - - #[test] - pub fn test_sub() { - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(3.0, 4.0); - assert_eq!(p1 - p2, Size2D::new(-2.0, -2.0)); - - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(0.0, 0.0); - assert_eq!(p1 - p2, Size2D::new(1.0, 2.0)); - - let p1 = Size2D::new(1.0, 2.0); - let p2 = Size2D::new(-3.0, -4.0); - assert_eq!(p1 - p2, Size2D::new(4.0, 6.0)); - - let p1 = Size2D::new(0.0, 0.0); - let p2 = Size2D::new(0.0, 0.0); - assert_eq!(p1 - p2, Size2D::new(0.0, 0.0)); - } - - #[test] - pub fn test_area() { - let p = Size2D::new(1.5, 2.0); - assert_eq!(p.area(), 3.0); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/transform2d.rs b/third_party/rust/euclid-0.17.3/src/transform2d.rs deleted file mode 100644 index a9ee210636bf..000000000000 --- a/third_party/rust/euclid-0.17.3/src/transform2d.rs +++ /dev/null @@ -1,525 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::{UnknownUnit, Angle}; -use num::{One, Zero}; -use point::TypedPoint2D; -use vector::{TypedVector2D, vec2}; -use rect::TypedRect; -use transform3d::TypedTransform3D; -use std::ops::{Add, Mul, Div, Sub, Neg}; -use std::marker::PhantomData; -use approxeq::ApproxEq; -use trig::Trig; -use std::fmt; -use num_traits::NumCast; - -define_matrix! { - /// A 2d transform stored as a 3 by 2 matrix in row-major order in memory. - /// - /// Transforms can be parametrized over the source and destination units, to describe a - /// transformation from a space to another. - /// For example, `TypedTransform2D::transform_point4d` - /// takes a `TypedPoint2D` and returns a `TypedPoint2D`. - /// - /// Transforms expose a set of convenience methods for pre- and post-transformations. - /// A pre-transformation corresponds to adding an operation that is applied before - /// the rest of the transformation, while a post-transformation adds an operation - /// that is applied after. - pub struct TypedTransform2D { - pub m11: T, pub m12: T, - pub m21: T, pub m22: T, - pub m31: T, pub m32: T, - } -} - -/// The default 2d transform type with no units. -pub type Transform2D = TypedTransform2D; - -impl TypedTransform2D { - /// Create a transform specifying its matrix elements in row-major order. - pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self { - TypedTransform2D { - m11: m11, m12: m12, - m21: m21, m22: m22, - m31: m31, m32: m32, - _unit: PhantomData, - } - } - - /// Create a transform specifying its matrix elements in column-major order. - pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self { - TypedTransform2D { - m11: m11, m12: m12, - m21: m21, m22: m22, - m31: m31, m32: m32, - _unit: PhantomData, - } - } - - /// Returns an array containing this transform's terms in row-major order (the order - /// in which the transform is actually laid out in memory). - pub fn to_row_major_array(&self) -> [T; 6] { - [ - self.m11, self.m12, - self.m21, self.m22, - self.m31, self.m32 - ] - } - - /// Returns an array containing this transform's terms in column-major order. - pub fn to_column_major_array(&self) -> [T; 6] { - [ - self.m11, self.m21, self.m31, - self.m12, self.m22, self.m32 - ] - } - - /// Returns an array containing this transform's 3 rows in (in row-major order) - /// as arrays. - /// - /// This is a convenience method to interface with other libraries like glium. - pub fn to_row_arrays(&self) -> [[T; 2]; 3] { - [ - [self.m11, self.m12], - [self.m21, self.m22], - [self.m31, self.m32], - ] - } - - /// Creates a transform from an array of 6 elements in row-major order. - pub fn from_row_major_array(array: [T; 6]) -> Self { - Self::row_major( - array[0], array[1], - array[2], array[3], - array[4], array[5], - ) - } - - /// Creates a transform from 3 rows of 2 elements (row-major order). - pub fn from_row_arrays(array: [[T; 2]; 3]) -> Self { - Self::row_major( - array[0][0], array[0][1], - array[1][0], array[1][1], - array[2][0], array[2][1], - ) - } - - /// Drop the units, preserving only the numeric value. - pub fn to_untyped(&self) -> Transform2D { - Transform2D::row_major( - self.m11, self.m12, - self.m21, self.m22, - self.m31, self.m32 - ) - } - - /// Tag a unitless value with units. - pub fn from_untyped(p: &Transform2D) -> Self { - TypedTransform2D::row_major( - p.m11, p.m12, - p.m21, p.m22, - p.m31, p.m32 - ) - } -} - -impl TypedTransform2D { - /// Cast from one numeric representation to another, preserving the units. - pub fn cast(&self) -> Option> { - match (NumCast::from(self.m11), NumCast::from(self.m12), - NumCast::from(self.m21), NumCast::from(self.m22), - NumCast::from(self.m31), NumCast::from(self.m32)) { - (Some(m11), Some(m12), - Some(m21), Some(m22), - Some(m31), Some(m32)) => { - Some(TypedTransform2D::row_major(m11, m12, - m21, m22, - m31, m32)) - }, - _ => None - } - } -} - -impl TypedTransform2D -where T: Copy + - PartialEq + - One + Zero { - pub fn identity() -> Self { - let (_0, _1) = (Zero::zero(), One::one()); - TypedTransform2D::row_major( - _1, _0, - _0, _1, - _0, _0 - ) - } - - // Intentional not public, because it checks for exact equivalence - // while most consumers will probably want some sort of approximate - // equivalence to deal with floating-point errors. - fn is_identity(&self) -> bool { - *self == TypedTransform2D::identity() - } -} - -impl TypedTransform2D -where T: Copy + Clone + - Add + - Mul + - Div + - Sub + - Trig + - PartialOrd + - One + Zero { - - /// Returns the multiplication of the two matrices such that mat's transformation - /// applies after self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_mul(&self, mat: &TypedTransform2D) -> TypedTransform2D { - TypedTransform2D::row_major( - self.m11 * mat.m11 + self.m12 * mat.m21, - self.m11 * mat.m12 + self.m12 * mat.m22, - self.m21 * mat.m11 + self.m22 * mat.m21, - self.m21 * mat.m12 + self.m22 * mat.m22, - self.m31 * mat.m11 + self.m32 * mat.m21 + mat.m31, - self.m31 * mat.m12 + self.m32 * mat.m22 + mat.m32, - ) - } - - /// Returns the multiplication of the two matrices such that mat's transformation - /// applies before self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_mul(&self, mat: &TypedTransform2D) -> TypedTransform2D { - mat.post_mul(self) - } - - /// Returns a translation transform. - pub fn create_translation(x: T, y: T) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform2D::row_major( - _1, _0, - _0, _1, - x, y - ) - } - - /// Applies a translation after self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_translate(&self, v: TypedVector2D) -> Self { - self.post_mul(&TypedTransform2D::create_translation(v.x, v.y)) - } - - /// Applies a translation before self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_translate(&self, v: TypedVector2D) -> Self { - self.pre_mul(&TypedTransform2D::create_translation(v.x, v.y)) - } - - /// Returns a scale transform. - pub fn create_scale(x: T, y: T) -> Self { - let _0 = Zero::zero(); - TypedTransform2D::row_major( - x, _0, - _0, y, - _0, _0 - ) - } - - /// Applies a scale after self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_scale(&self, x: T, y: T) -> Self { - self.post_mul(&TypedTransform2D::create_scale(x, y)) - } - - /// Applies a scale before self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_scale(&self, x: T, y: T) -> Self { - TypedTransform2D::row_major( - self.m11 * x, self.m12, - self.m21, self.m22 * y, - self.m31, self.m32 - ) - } - - /// Returns a rotation transform. - pub fn create_rotation(theta: Angle) -> Self { - let _0 = Zero::zero(); - let cos = theta.get().cos(); - let sin = theta.get().sin(); - TypedTransform2D::row_major( - cos, _0 - sin, - sin, cos, - _0, _0 - ) - } - - /// Applies a rotation after self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_rotate(&self, theta: Angle) -> Self { - self.post_mul(&TypedTransform2D::create_rotation(theta)) - } - - /// Applies a rotation after self's transformation and returns the resulting transform. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_rotate(&self, theta: Angle) -> Self { - self.pre_mul(&TypedTransform2D::create_rotation(theta)) - } - - /// Returns the given point transformed by this transform. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn transform_point(&self, point: &TypedPoint2D) -> TypedPoint2D { - TypedPoint2D::new(point.x * self.m11 + point.y * self.m21 + self.m31, - point.x * self.m12 + point.y * self.m22 + self.m32) - } - - /// Returns the given vector transformed by this matrix. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn transform_vector(&self, vec: &TypedVector2D) -> TypedVector2D { - vec2(vec.x * self.m11 + vec.y * self.m21, - vec.x * self.m12 + vec.y * self.m22) - } - - /// Returns a rectangle that encompasses the result of transforming the given rectangle by this - /// transform. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn transform_rect(&self, rect: &TypedRect) -> TypedRect { - TypedRect::from_points(&[ - self.transform_point(&rect.origin), - self.transform_point(&rect.top_right()), - self.transform_point(&rect.bottom_left()), - self.transform_point(&rect.bottom_right()), - ]) - } - - /// Computes and returns the determinant of this transform. - pub fn determinant(&self) -> T { - self.m11 * self.m22 - self.m12 * self.m21 - } - - /// Returns the inverse transform if possible. - #[cfg_attr(feature = "unstable", must_use)] - pub fn inverse(&self) -> Option> { - let det = self.determinant(); - - let _0: T = Zero::zero(); - let _1: T = One::one(); - - if det == _0 { - return None; - } - - let inv_det = _1 / det; - Some(TypedTransform2D::row_major( - inv_det * self.m22, - inv_det * (_0 - self.m12), - inv_det * (_0 - self.m21), - inv_det * self.m11, - inv_det * (self.m21 * self.m32 - self.m22 * self.m31), - inv_det * (self.m31 * self.m12 - self.m11 * self.m32), - )) - } - - /// Returns the same transform with a different destination unit. - #[inline] - pub fn with_destination(&self) -> TypedTransform2D { - TypedTransform2D::row_major( - self.m11, self.m12, - self.m21, self.m22, - self.m31, self.m32, - ) - } - - /// Returns the same transform with a different source unit. - #[inline] - pub fn with_source(&self) -> TypedTransform2D { - TypedTransform2D::row_major( - self.m11, self.m12, - self.m21, self.m22, - self.m31, self.m32, - ) - } -} - -impl TypedTransform2D -where T: Copy + Clone + - Add + - Sub + - Mul + - Div + - Neg + - PartialOrd + - Trig + - One + Zero { - /// Create a 3D transform from the current transform - pub fn to_3d(&self) -> TypedTransform3D { - TypedTransform3D::row_major_2d(self.m11, self.m12, self.m21, self.m22, self.m31, self.m32) - } - -} - -impl, Src, Dst> TypedTransform2D { - pub fn approx_eq(&self, other: &Self) -> bool { - self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) && - self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) && - self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) - } -} - -impl fmt::Debug for TypedTransform2D -where T: Copy + fmt::Debug + - PartialEq + - One + Zero { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.is_identity() { - write!(f, "[I]") - } else { - self.to_row_major_array().fmt(f) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use approxeq::ApproxEq; - use point::Point2D; - use Angle; - - use std::f32::consts::FRAC_PI_2; - - type Mat = Transform2D; - - fn rad(v: f32) -> Angle { Angle::radians(v) } - - #[test] - pub fn test_translation() { - let t1 = Mat::create_translation(1.0, 2.0); - let t2 = Mat::identity().pre_translate(vec2(1.0, 2.0)); - let t3 = Mat::identity().post_translate(vec2(1.0, 2.0)); - assert_eq!(t1, t2); - assert_eq!(t1, t3); - - assert_eq!(t1.transform_point(&Point2D::new(1.0, 1.0)), Point2D::new(2.0, 3.0)); - - assert_eq!(t1.post_mul(&t1), Mat::create_translation(2.0, 4.0)); - } - - #[test] - pub fn test_rotation() { - let r1 = Mat::create_rotation(rad(FRAC_PI_2)); - let r2 = Mat::identity().pre_rotate(rad(FRAC_PI_2)); - let r3 = Mat::identity().post_rotate(rad(FRAC_PI_2)); - assert_eq!(r1, r2); - assert_eq!(r1, r3); - - assert!(r1.transform_point(&Point2D::new(1.0, 2.0)).approx_eq(&Point2D::new(2.0, -1.0))); - - assert!(r1.post_mul(&r1).approx_eq(&Mat::create_rotation(rad(FRAC_PI_2*2.0)))); - } - - #[test] - pub fn test_scale() { - let s1 = Mat::create_scale(2.0, 3.0); - let s2 = Mat::identity().pre_scale(2.0, 3.0); - let s3 = Mat::identity().post_scale(2.0, 3.0); - assert_eq!(s1, s2); - assert_eq!(s1, s3); - - assert!(s1.transform_point(&Point2D::new(2.0, 2.0)).approx_eq(&Point2D::new(4.0, 6.0))); - } - - #[test] - fn test_column_major() { - assert_eq!( - Mat::row_major( - 1.0, 2.0, - 3.0, 4.0, - 5.0, 6.0 - ), - Mat::column_major( - 1.0, 3.0, 5.0, - 2.0, 4.0, 6.0, - ) - ); - } - - #[test] - pub fn test_inverse_simple() { - let m1 = Mat::identity(); - let m2 = m1.inverse().unwrap(); - assert!(m1.approx_eq(&m2)); - } - - #[test] - pub fn test_inverse_scale() { - let m1 = Mat::create_scale(1.5, 0.3); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity())); - } - - #[test] - pub fn test_inverse_translate() { - let m1 = Mat::create_translation(-132.0, 0.3); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity())); - } - - #[test] - fn test_inverse_none() { - assert!(Mat::create_scale(2.0, 0.0).inverse().is_none()); - assert!(Mat::create_scale(2.0, 2.0).inverse().is_some()); - } - - #[test] - pub fn test_pre_post() { - let m1 = Transform2D::identity().post_scale(1.0, 2.0).post_translate(vec2(1.0, 2.0)); - let m2 = Transform2D::identity().pre_translate(vec2(1.0, 2.0)).pre_scale(1.0, 2.0); - assert!(m1.approx_eq(&m2)); - - let r = Mat::create_rotation(rad(FRAC_PI_2)); - let t = Mat::create_translation(2.0, 3.0); - - let a = Point2D::new(1.0, 1.0); - - assert!(r.post_mul(&t).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0))); - assert!(t.post_mul(&r).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0))); - assert!(t.post_mul(&r).transform_point(&a).approx_eq(&r.transform_point(&t.transform_point(&a)))); - - assert!(r.pre_mul(&t).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0))); - assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0))); - assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&t.transform_point(&r.transform_point(&a)))); - } - - #[test] - fn test_size_of() { - use std::mem::size_of; - assert_eq!(size_of::>(), 6*size_of::()); - assert_eq!(size_of::>(), 6*size_of::()); - } - - #[test] - pub fn test_is_identity() { - let m1 = Transform2D::identity(); - assert!(m1.is_identity()); - let m2 = m1.post_translate(vec2(0.1, 0.0)); - assert!(!m2.is_identity()); - } - - #[test] - pub fn test_transform_vector() { - // Translation does not apply to vectors. - let m1 = Mat::create_translation(1.0, 1.0); - let v1 = vec2(10.0, -10.0); - assert_eq!(v1, m1.transform_vector(&v1)); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/transform3d.rs b/third_party/rust/euclid-0.17.3/src/transform3d.rs deleted file mode 100644 index d72bd81709a5..000000000000 --- a/third_party/rust/euclid-0.17.3/src/transform3d.rs +++ /dev/null @@ -1,990 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::{UnknownUnit, Angle}; -use approxeq::ApproxEq; -use homogen::HomogeneousVector; -use trig::Trig; -use point::{TypedPoint2D, TypedPoint3D}; -use vector::{TypedVector2D, TypedVector3D, vec2, vec3}; -use rect::TypedRect; -use transform2d::TypedTransform2D; -use scale::TypedScale; -use num::{One, Zero}; -use std::ops::{Add, Mul, Sub, Div, Neg}; -use std::marker::PhantomData; -use std::fmt; -use num_traits::NumCast; - -define_matrix! { - /// A 3d transform stored as a 4 by 4 matrix in row-major order in memory. - /// - /// Transforms can be parametrized over the source and destination units, to describe a - /// transformation from a space to another. - /// For example, `TypedTransform3D::transform_point3d` - /// takes a `TypedPoint3D` and returns a `TypedPoint3D`. - /// - /// Transforms expose a set of convenience methods for pre- and post-transformations. - /// A pre-transformation corresponds to adding an operation that is applied before - /// the rest of the transformation, while a post-transformation adds an operation - /// that is applied after. - pub struct TypedTransform3D { - pub m11: T, pub m12: T, pub m13: T, pub m14: T, - pub m21: T, pub m22: T, pub m23: T, pub m24: T, - pub m31: T, pub m32: T, pub m33: T, pub m34: T, - pub m41: T, pub m42: T, pub m43: T, pub m44: T, - } -} - -/// The default 3d transform type with no units. -pub type Transform3D = TypedTransform3D; - -impl TypedTransform3D { - /// Create a transform specifying its components in row-major order. - /// - /// For example, the translation terms m41, m42, m43 on the last row with the - /// row-major convention) are the 13rd, 14th and 15th parameters. - #[inline] - pub fn row_major( - m11: T, m12: T, m13: T, m14: T, - m21: T, m22: T, m23: T, m24: T, - m31: T, m32: T, m33: T, m34: T, - m41: T, m42: T, m43: T, m44: T) - -> Self { - TypedTransform3D { - m11: m11, m12: m12, m13: m13, m14: m14, - m21: m21, m22: m22, m23: m23, m24: m24, - m31: m31, m32: m32, m33: m33, m34: m34, - m41: m41, m42: m42, m43: m43, m44: m44, - _unit: PhantomData, - } - } - - /// Create a transform specifying its components in column-major order. - /// - /// For example, the translation terms m41, m42, m43 on the last column with the - /// column-major convention) are the 4th, 8th and 12nd parameters. - #[inline] - pub fn column_major( - m11: T, m21: T, m31: T, m41: T, - m12: T, m22: T, m32: T, m42: T, - m13: T, m23: T, m33: T, m43: T, - m14: T, m24: T, m34: T, m44: T) - -> Self { - TypedTransform3D { - m11: m11, m12: m12, m13: m13, m14: m14, - m21: m21, m22: m22, m23: m23, m24: m24, - m31: m31, m32: m32, m33: m33, m34: m34, - m41: m41, m42: m42, m43: m43, m44: m44, - _unit: PhantomData, - } - } -} - -impl TypedTransform3D -where T: Copy + Clone + - PartialEq + - One + Zero { - #[inline] - pub fn identity() -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform3D::row_major( - _1, _0, _0, _0, - _0, _1, _0, _0, - _0, _0, _1, _0, - _0, _0, _0, _1 - ) - } - - // Intentional not public, because it checks for exact equivalence - // while most consumers will probably want some sort of approximate - // equivalence to deal with floating-point errors. - #[inline] - fn is_identity(&self) -> bool { - *self == TypedTransform3D::identity() - } -} - -impl TypedTransform3D -where T: Copy + Clone + - Add + - Sub + - Mul + - Div + - Neg + - PartialOrd + - Trig + - One + Zero { - - /// Create a 4 by 4 transform representing a 2d transformation, specifying its components - /// in row-major order. - #[inline] - pub fn row_major_2d(m11: T, m12: T, m21: T, m22: T, m41: T, m42: T) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform3D::row_major( - m11, m12, _0, _0, - m21, m22, _0, _0, - _0, _0, _1, _0, - m41, m42, _0, _1 - ) - } - - /// Create an orthogonal projection transform. - pub fn ortho(left: T, right: T, - bottom: T, top: T, - near: T, far: T) -> Self { - let tx = -((right + left) / (right - left)); - let ty = -((top + bottom) / (top - bottom)); - let tz = -((far + near) / (far - near)); - - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - let _2 = _1 + _1; - TypedTransform3D::row_major( - _2 / (right - left), _0 , _0 , _0, - _0 , _2 / (top - bottom), _0 , _0, - _0 , _0 , -_2 / (far - near), _0, - tx , ty , tz , _1 - ) - } - - /// Returns true if this transform can be represented with a `TypedTransform2D`. - /// - /// See - #[inline] - pub fn is_2d(&self) -> bool { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - self.m31 == _0 && self.m32 == _0 && - self.m13 == _0 && self.m23 == _0 && - self.m43 == _0 && self.m14 == _0 && - self.m24 == _0 && self.m34 == _0 && - self.m33 == _1 && self.m44 == _1 - } - - /// Create a 2D transform picking the relevant terms from this transform. - /// - /// This method assumes that self represents a 2d transformation, callers - /// should check that self.is_2d() returns true beforehand. - pub fn to_2d(&self) -> TypedTransform2D { - TypedTransform2D::row_major( - self.m11, self.m12, - self.m21, self.m22, - self.m41, self.m42 - ) - } - - /// Check whether shapes on the XY plane with Z pointing towards the - /// screen transformed by this matrix would be facing back. - pub fn is_backface_visible(&self) -> bool { - // inverse().m33 < 0; - let det = self.determinant(); - let m33 = self.m12 * self.m24 * self.m41 - self.m14 * self.m22 * self.m41 + - self.m14 * self.m21 * self.m42 - self.m11 * self.m24 * self.m42 - - self.m12 * self.m21 * self.m44 + self.m11 * self.m22 * self.m44; - let _0: T = Zero::zero(); - (m33 * det) < _0 - } - - pub fn approx_eq(&self, other: &Self) -> bool - where T : ApproxEq { - self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) && - self.m13.approx_eq(&other.m13) && self.m14.approx_eq(&other.m14) && - self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) && - self.m23.approx_eq(&other.m23) && self.m24.approx_eq(&other.m24) && - self.m31.approx_eq(&other.m31) && self.m32.approx_eq(&other.m32) && - self.m33.approx_eq(&other.m33) && self.m34.approx_eq(&other.m34) && - self.m41.approx_eq(&other.m41) && self.m42.approx_eq(&other.m42) && - self.m43.approx_eq(&other.m43) && self.m44.approx_eq(&other.m44) - } - - /// Returns the same transform with a different destination unit. - #[inline] - pub fn with_destination(&self) -> TypedTransform3D { - TypedTransform3D::row_major( - self.m11, self.m12, self.m13, self.m14, - self.m21, self.m22, self.m23, self.m24, - self.m31, self.m32, self.m33, self.m34, - self.m41, self.m42, self.m43, self.m44, - ) - } - - /// Returns the same transform with a different source unit. - #[inline] - pub fn with_source(&self) -> TypedTransform3D { - TypedTransform3D::row_major( - self.m11, self.m12, self.m13, self.m14, - self.m21, self.m22, self.m23, self.m24, - self.m31, self.m32, self.m33, self.m34, - self.m41, self.m42, self.m43, self.m44, - ) - } - - /// Drop the units, preserving only the numeric value. - #[inline] - pub fn to_untyped(&self) -> Transform3D { - Transform3D::row_major( - self.m11, self.m12, self.m13, self.m14, - self.m21, self.m22, self.m23, self.m24, - self.m31, self.m32, self.m33, self.m34, - self.m41, self.m42, self.m43, self.m44, - ) - } - - /// Tag a unitless value with units. - #[inline] - pub fn from_untyped(m: &Transform3D) -> Self { - TypedTransform3D::row_major( - m.m11, m.m12, m.m13, m.m14, - m.m21, m.m22, m.m23, m.m24, - m.m31, m.m32, m.m33, m.m34, - m.m41, m.m42, m.m43, m.m44, - ) - } - - /// Returns the multiplication of the two matrices such that mat's transformation - /// applies after self's transformation. - pub fn post_mul(&self, mat: &TypedTransform3D) -> TypedTransform3D { - TypedTransform3D::row_major( - self.m11 * mat.m11 + self.m12 * mat.m21 + self.m13 * mat.m31 + self.m14 * mat.m41, - self.m11 * mat.m12 + self.m12 * mat.m22 + self.m13 * mat.m32 + self.m14 * mat.m42, - self.m11 * mat.m13 + self.m12 * mat.m23 + self.m13 * mat.m33 + self.m14 * mat.m43, - self.m11 * mat.m14 + self.m12 * mat.m24 + self.m13 * mat.m34 + self.m14 * mat.m44, - self.m21 * mat.m11 + self.m22 * mat.m21 + self.m23 * mat.m31 + self.m24 * mat.m41, - self.m21 * mat.m12 + self.m22 * mat.m22 + self.m23 * mat.m32 + self.m24 * mat.m42, - self.m21 * mat.m13 + self.m22 * mat.m23 + self.m23 * mat.m33 + self.m24 * mat.m43, - self.m21 * mat.m14 + self.m22 * mat.m24 + self.m23 * mat.m34 + self.m24 * mat.m44, - self.m31 * mat.m11 + self.m32 * mat.m21 + self.m33 * mat.m31 + self.m34 * mat.m41, - self.m31 * mat.m12 + self.m32 * mat.m22 + self.m33 * mat.m32 + self.m34 * mat.m42, - self.m31 * mat.m13 + self.m32 * mat.m23 + self.m33 * mat.m33 + self.m34 * mat.m43, - self.m31 * mat.m14 + self.m32 * mat.m24 + self.m33 * mat.m34 + self.m34 * mat.m44, - self.m41 * mat.m11 + self.m42 * mat.m21 + self.m43 * mat.m31 + self.m44 * mat.m41, - self.m41 * mat.m12 + self.m42 * mat.m22 + self.m43 * mat.m32 + self.m44 * mat.m42, - self.m41 * mat.m13 + self.m42 * mat.m23 + self.m43 * mat.m33 + self.m44 * mat.m43, - self.m41 * mat.m14 + self.m42 * mat.m24 + self.m43 * mat.m34 + self.m44 * mat.m44, - ) - } - - /// Returns the multiplication of the two matrices such that mat's transformation - /// applies before self's transformation. - pub fn pre_mul(&self, mat: &TypedTransform3D) -> TypedTransform3D { - mat.post_mul(self) - } - - /// Returns the inverse transform if possible. - pub fn inverse(&self) -> Option> { - let det = self.determinant(); - - if det == Zero::zero() { - return None; - } - - // todo(gw): this could be made faster by special casing - // for simpler transform types. - let m = TypedTransform3D::row_major( - self.m23*self.m34*self.m42 - self.m24*self.m33*self.m42 + - self.m24*self.m32*self.m43 - self.m22*self.m34*self.m43 - - self.m23*self.m32*self.m44 + self.m22*self.m33*self.m44, - - self.m14*self.m33*self.m42 - self.m13*self.m34*self.m42 - - self.m14*self.m32*self.m43 + self.m12*self.m34*self.m43 + - self.m13*self.m32*self.m44 - self.m12*self.m33*self.m44, - - self.m13*self.m24*self.m42 - self.m14*self.m23*self.m42 + - self.m14*self.m22*self.m43 - self.m12*self.m24*self.m43 - - self.m13*self.m22*self.m44 + self.m12*self.m23*self.m44, - - self.m14*self.m23*self.m32 - self.m13*self.m24*self.m32 - - self.m14*self.m22*self.m33 + self.m12*self.m24*self.m33 + - self.m13*self.m22*self.m34 - self.m12*self.m23*self.m34, - - self.m24*self.m33*self.m41 - self.m23*self.m34*self.m41 - - self.m24*self.m31*self.m43 + self.m21*self.m34*self.m43 + - self.m23*self.m31*self.m44 - self.m21*self.m33*self.m44, - - self.m13*self.m34*self.m41 - self.m14*self.m33*self.m41 + - self.m14*self.m31*self.m43 - self.m11*self.m34*self.m43 - - self.m13*self.m31*self.m44 + self.m11*self.m33*self.m44, - - self.m14*self.m23*self.m41 - self.m13*self.m24*self.m41 - - self.m14*self.m21*self.m43 + self.m11*self.m24*self.m43 + - self.m13*self.m21*self.m44 - self.m11*self.m23*self.m44, - - self.m13*self.m24*self.m31 - self.m14*self.m23*self.m31 + - self.m14*self.m21*self.m33 - self.m11*self.m24*self.m33 - - self.m13*self.m21*self.m34 + self.m11*self.m23*self.m34, - - self.m22*self.m34*self.m41 - self.m24*self.m32*self.m41 + - self.m24*self.m31*self.m42 - self.m21*self.m34*self.m42 - - self.m22*self.m31*self.m44 + self.m21*self.m32*self.m44, - - self.m14*self.m32*self.m41 - self.m12*self.m34*self.m41 - - self.m14*self.m31*self.m42 + self.m11*self.m34*self.m42 + - self.m12*self.m31*self.m44 - self.m11*self.m32*self.m44, - - self.m12*self.m24*self.m41 - self.m14*self.m22*self.m41 + - self.m14*self.m21*self.m42 - self.m11*self.m24*self.m42 - - self.m12*self.m21*self.m44 + self.m11*self.m22*self.m44, - - self.m14*self.m22*self.m31 - self.m12*self.m24*self.m31 - - self.m14*self.m21*self.m32 + self.m11*self.m24*self.m32 + - self.m12*self.m21*self.m34 - self.m11*self.m22*self.m34, - - self.m23*self.m32*self.m41 - self.m22*self.m33*self.m41 - - self.m23*self.m31*self.m42 + self.m21*self.m33*self.m42 + - self.m22*self.m31*self.m43 - self.m21*self.m32*self.m43, - - self.m12*self.m33*self.m41 - self.m13*self.m32*self.m41 + - self.m13*self.m31*self.m42 - self.m11*self.m33*self.m42 - - self.m12*self.m31*self.m43 + self.m11*self.m32*self.m43, - - self.m13*self.m22*self.m41 - self.m12*self.m23*self.m41 - - self.m13*self.m21*self.m42 + self.m11*self.m23*self.m42 + - self.m12*self.m21*self.m43 - self.m11*self.m22*self.m43, - - self.m12*self.m23*self.m31 - self.m13*self.m22*self.m31 + - self.m13*self.m21*self.m32 - self.m11*self.m23*self.m32 - - self.m12*self.m21*self.m33 + self.m11*self.m22*self.m33 - ); - - let _1: T = One::one(); - Some(m.mul_s(_1 / det)) - } - - /// Compute the determinant of the transform. - pub fn determinant(&self) -> T { - self.m14 * self.m23 * self.m32 * self.m41 - - self.m13 * self.m24 * self.m32 * self.m41 - - self.m14 * self.m22 * self.m33 * self.m41 + - self.m12 * self.m24 * self.m33 * self.m41 + - self.m13 * self.m22 * self.m34 * self.m41 - - self.m12 * self.m23 * self.m34 * self.m41 - - self.m14 * self.m23 * self.m31 * self.m42 + - self.m13 * self.m24 * self.m31 * self.m42 + - self.m14 * self.m21 * self.m33 * self.m42 - - self.m11 * self.m24 * self.m33 * self.m42 - - self.m13 * self.m21 * self.m34 * self.m42 + - self.m11 * self.m23 * self.m34 * self.m42 + - self.m14 * self.m22 * self.m31 * self.m43 - - self.m12 * self.m24 * self.m31 * self.m43 - - self.m14 * self.m21 * self.m32 * self.m43 + - self.m11 * self.m24 * self.m32 * self.m43 + - self.m12 * self.m21 * self.m34 * self.m43 - - self.m11 * self.m22 * self.m34 * self.m43 - - self.m13 * self.m22 * self.m31 * self.m44 + - self.m12 * self.m23 * self.m31 * self.m44 + - self.m13 * self.m21 * self.m32 * self.m44 - - self.m11 * self.m23 * self.m32 * self.m44 - - self.m12 * self.m21 * self.m33 * self.m44 + - self.m11 * self.m22 * self.m33 * self.m44 - } - - /// Multiplies all of the transform's component by a scalar and returns the result. - #[cfg_attr(feature = "unstable", must_use)] - pub fn mul_s(&self, x: T) -> Self { - TypedTransform3D::row_major( - self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x, - self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x, - self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x, - self.m41 * x, self.m42 * x, self.m43 * x, self.m44 * x - ) - } - - /// Convenience function to create a scale transform from a `TypedScale`. - pub fn from_scale(scale: TypedScale) -> Self { - TypedTransform3D::create_scale(scale.get(), scale.get(), scale.get()) - } - - /// Returns the homogeneous vector corresponding to the transformed 2d point. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_point2d_homogeneous( - &self, p: &TypedPoint2D - ) -> HomogeneousVector { - let x = p.x * self.m11 + p.y * self.m21 + self.m41; - let y = p.x * self.m12 + p.y * self.m22 + self.m42; - let z = p.x * self.m13 + p.y * self.m23 + self.m43; - let w = p.x * self.m14 + p.y * self.m24 + self.m44; - - HomogeneousVector::new(x, y, z, w) - } - - /// Returns the given 2d point transformed by this transform. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_point2d(&self, p: &TypedPoint2D) -> TypedPoint2D { - //Note: could use `transform_point2d_homogeneous()` but it would waste the calculus of `z` - - let x = p.x * self.m11 + p.y * self.m21 + self.m41; - let y = p.x * self.m12 + p.y * self.m22 + self.m42; - let w = p.x * self.m14 + p.y * self.m24 + self.m44; - - - TypedPoint2D::new(x / w, y / w) - } - - /// Returns the given 2d vector transformed by this matrix. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_vector2d(&self, v: &TypedVector2D) -> TypedVector2D { - vec2( - v.x * self.m11 + v.y * self.m21, - v.x * self.m12 + v.y * self.m22, - ) - } - - /// Returns the homogeneous vector corresponding to the transformed 3d point. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_point3d_homogeneous( - &self, p: &TypedPoint3D - ) -> HomogeneousVector { - let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41; - let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42; - let z = p.x * self.m13 + p.y * self.m23 + p.z * self.m33 + self.m43; - let w = p.x * self.m14 + p.y * self.m24 + p.z * self.m34 + self.m44; - - HomogeneousVector::new(x, y, z, w) - } - - /// Returns the given 3d point transformed by this transform. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_point3d(&self, p: &TypedPoint3D) -> TypedPoint3D { - self.transform_point3d_homogeneous(p).to_point3d() - } - - /// Returns the given 3d vector transformed by this matrix. - /// - /// The input point must be use the unit Src, and the returned point has the unit Dst. - #[inline] - pub fn transform_vector3d(&self, v: &TypedVector3D) -> TypedVector3D { - vec3( - v.x * self.m11 + v.y * self.m21 + v.z * self.m31, - v.x * self.m12 + v.y * self.m22 + v.z * self.m32, - v.x * self.m13 + v.y * self.m23 + v.z * self.m33, - ) - } - - /// Returns a rectangle that encompasses the result of transforming the given rectangle by this - /// transform. - pub fn transform_rect(&self, rect: &TypedRect) -> TypedRect { - TypedRect::from_points(&[ - self.transform_point2d(&rect.origin), - self.transform_point2d(&rect.top_right()), - self.transform_point2d(&rect.bottom_left()), - self.transform_point2d(&rect.bottom_right()), - ]) - } - - /// Create a 3d translation transform - pub fn create_translation(x: T, y: T, z: T) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform3D::row_major( - _1, _0, _0, _0, - _0, _1, _0, _0, - _0, _0, _1, _0, - x, y, z, _1 - ) - } - - /// Returns a transform with a translation applied before self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_translate(&self, v: TypedVector3D) -> Self { - self.pre_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z)) - } - - /// Returns a transform with a translation applied after self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_translate(&self, v: TypedVector3D) -> Self { - self.post_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z)) - } - - /// Create a 3d scale transform - pub fn create_scale(x: T, y: T, z: T) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform3D::row_major( - x, _0, _0, _0, - _0, y, _0, _0, - _0, _0, z, _0, - _0, _0, _0, _1 - ) - } - - /// Returns a transform with a scale applied before self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_scale(&self, x: T, y: T, z: T) -> Self { - TypedTransform3D::row_major( - self.m11 * x, self.m12, self.m13, self.m14, - self.m21 , self.m22 * y, self.m23, self.m24, - self.m31 , self.m32, self.m33 * z, self.m34, - self.m41 , self.m42, self.m43, self.m44 - ) - } - - /// Returns a transform with a scale applied after self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_scale(&self, x: T, y: T, z: T) -> Self { - self.post_mul(&TypedTransform3D::create_scale(x, y, z)) - } - - /// Create a 3d rotation transform from an angle / axis. - /// The supplied axis must be normalized. - pub fn create_rotation(x: T, y: T, z: T, theta: Angle) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - let _2 = _1 + _1; - - let xx = x * x; - let yy = y * y; - let zz = z * z; - - let half_theta = theta.get() / _2; - let sc = half_theta.sin() * half_theta.cos(); - let sq = half_theta.sin() * half_theta.sin(); - - TypedTransform3D::row_major( - _1 - _2 * (yy + zz) * sq, - _2 * (x * y * sq - z * sc), - _2 * (x * z * sq + y * sc), - _0, - - _2 * (x * y * sq + z * sc), - _1 - _2 * (xx + zz) * sq, - _2 * (y * z * sq - x * sc), - _0, - - _2 * (x * z * sq - y * sc), - _2 * (y * z * sq + x * sc), - _1 - _2 * (xx + yy) * sq, - _0, - - _0, - _0, - _0, - _1 - ) - } - - /// Returns a transform with a rotation applied after self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn post_rotate(&self, x: T, y: T, z: T, theta: Angle) -> Self { - self.post_mul(&TypedTransform3D::create_rotation(x, y, z, theta)) - } - - /// Returns a transform with a rotation applied before self's transformation. - #[cfg_attr(feature = "unstable", must_use)] - pub fn pre_rotate(&self, x: T, y: T, z: T, theta: Angle) -> Self { - self.pre_mul(&TypedTransform3D::create_rotation(x, y, z, theta)) - } - - /// Create a 2d skew transform. - /// - /// See - pub fn create_skew(alpha: Angle, beta: Angle) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - let (sx, sy) = (beta.get().tan(), alpha.get().tan()); - TypedTransform3D::row_major( - _1, sx, _0, _0, - sy, _1, _0, _0, - _0, _0, _1, _0, - _0, _0, _0, _1 - ) - } - - /// Create a simple perspective projection transform - pub fn create_perspective(d: T) -> Self { - let (_0, _1): (T, T) = (Zero::zero(), One::one()); - TypedTransform3D::row_major( - _1, _0, _0, _0, - _0, _1, _0, _0, - _0, _0, _1, -_1 / d, - _0, _0, _0, _1 - ) - } -} - -impl TypedTransform3D { - /// Returns an array containing this transform's terms in row-major order (the order - /// in which the transform is actually laid out in memory). - pub fn to_row_major_array(&self) -> [T; 16] { - [ - self.m11, self.m12, self.m13, self.m14, - self.m21, self.m22, self.m23, self.m24, - self.m31, self.m32, self.m33, self.m34, - self.m41, self.m42, self.m43, self.m44 - ] - } - - /// Returns an array containing this transform's terms in column-major order. - pub fn to_column_major_array(&self) -> [T; 16] { - [ - self.m11, self.m21, self.m31, self.m41, - self.m12, self.m22, self.m32, self.m42, - self.m13, self.m23, self.m33, self.m43, - self.m14, self.m24, self.m34, self.m44 - ] - } - - /// Returns an array containing this transform's 4 rows in (in row-major order) - /// as arrays. - /// - /// This is a convenience method to interface with other libraries like glium. - pub fn to_row_arrays(&self) -> [[T; 4]; 4] { - [ - [self.m11, self.m12, self.m13, self.m14], - [self.m21, self.m22, self.m23, self.m24], - [self.m31, self.m32, self.m33, self.m34], - [self.m41, self.m42, self.m43, self.m44] - ] - } - - /// Returns an array containing this transform's 4 columns in (in row-major order, - /// or 4 rows in column-major order) as arrays. - /// - /// This is a convenience method to interface with other libraries like glium. - pub fn to_column_arrays(&self) -> [[T; 4]; 4] { - [ - [self.m11, self.m21, self.m31, self.m41], - [self.m12, self.m22, self.m32, self.m42], - [self.m13, self.m23, self.m33, self.m43], - [self.m14, self.m24, self.m34, self.m44] - ] - } - - /// Creates a transform from an array of 16 elements in row-major order. - pub fn from_array(array: [T; 16]) -> Self { - Self::row_major( - array[0], array[1], array[2], array[3], - array[4], array[5], array[6], array[7], - array[8], array[9], array[10], array[11], - array[12], array[13], array[14], array[15], - ) - } - - /// Creates a transform from 4 rows of 4 elements (row-major order). - pub fn from_row_arrays(array: [[T; 4]; 4]) -> Self { - Self::row_major( - array[0][0], array[0][1], array[0][2], array[0][3], - array[1][0], array[1][1], array[1][2], array[1][3], - array[2][0], array[2][1], array[2][2], array[2][3], - array[3][0], array[3][1], array[3][2], array[3][3], - ) - } -} - -impl TypedTransform3D { - /// Cast from one numeric representation to another, preserving the units. - pub fn cast(&self) -> Option> { - match (NumCast::from(self.m11), NumCast::from(self.m12), - NumCast::from(self.m13), NumCast::from(self.m14), - NumCast::from(self.m21), NumCast::from(self.m22), - NumCast::from(self.m23), NumCast::from(self.m24), - NumCast::from(self.m31), NumCast::from(self.m32), - NumCast::from(self.m33), NumCast::from(self.m34), - NumCast::from(self.m41), NumCast::from(self.m42), - NumCast::from(self.m43), NumCast::from(self.m44)) { - (Some(m11), Some(m12), Some(m13), Some(m14), - Some(m21), Some(m22), Some(m23), Some(m24), - Some(m31), Some(m32), Some(m33), Some(m34), - Some(m41), Some(m42), Some(m43), Some(m44)) => { - Some(TypedTransform3D::row_major(m11, m12, m13, m14, - m21, m22, m23, m24, - m31, m32, m33, m34, - m41, m42, m43, m44)) - }, - _ => None - } - } -} - -impl fmt::Debug for TypedTransform3D -where T: Copy + fmt::Debug + - PartialEq + - One + Zero { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.is_identity() { - write!(f, "[I]") - } else { - self.to_row_major_array().fmt(f) - } - } -} - -#[cfg(test)] -mod tests { - use approxeq::ApproxEq; - use transform2d::Transform2D; - use point::{point2, point3}; - use Angle; - use super::*; - - use std::f32::consts::{FRAC_PI_2, PI}; - - type Mf32 = Transform3D; - - // For convenience. - fn rad(v: f32) -> Angle { Angle::radians(v) } - - #[test] - pub fn test_translation() { - let t1 = Mf32::create_translation(1.0, 2.0, 3.0); - let t2 = Mf32::identity().pre_translate(vec3(1.0, 2.0, 3.0)); - let t3 = Mf32::identity().post_translate(vec3(1.0, 2.0, 3.0)); - assert_eq!(t1, t2); - assert_eq!(t1, t3); - - assert_eq!(t1.transform_point3d(&point3(1.0, 1.0, 1.0)), point3(2.0, 3.0, 4.0)); - assert_eq!(t1.transform_point2d(&point2(1.0, 1.0)), point2(2.0, 3.0)); - - assert_eq!(t1.post_mul(&t1), Mf32::create_translation(2.0, 4.0, 6.0)); - - assert!(!t1.is_2d()); - assert_eq!(Mf32::create_translation(1.0, 2.0, 3.0).to_2d(), Transform2D::create_translation(1.0, 2.0)); - } - - #[test] - pub fn test_rotation() { - let r1 = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2)); - let r2 = Mf32::identity().pre_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2)); - let r3 = Mf32::identity().post_rotate(0.0, 0.0, 1.0, rad(FRAC_PI_2)); - assert_eq!(r1, r2); - assert_eq!(r1, r3); - - assert!(r1.transform_point3d(&point3(1.0, 2.0, 3.0)).approx_eq(&point3(2.0, -1.0, 3.0))); - assert!(r1.transform_point2d(&point2(1.0, 2.0)).approx_eq(&point2(2.0, -1.0))); - - assert!(r1.post_mul(&r1).approx_eq(&Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2*2.0)))); - - assert!(r1.is_2d()); - assert!(r1.to_2d().approx_eq(&Transform2D::create_rotation(rad(FRAC_PI_2)))); - } - - #[test] - pub fn test_scale() { - let s1 = Mf32::create_scale(2.0, 3.0, 4.0); - let s2 = Mf32::identity().pre_scale(2.0, 3.0, 4.0); - let s3 = Mf32::identity().post_scale(2.0, 3.0, 4.0); - assert_eq!(s1, s2); - assert_eq!(s1, s3); - - assert!(s1.transform_point3d(&point3(2.0, 2.0, 2.0)).approx_eq(&point3(4.0, 6.0, 8.0))); - assert!(s1.transform_point2d(&point2(2.0, 2.0)).approx_eq(&point2(4.0, 6.0))); - - assert_eq!(s1.post_mul(&s1), Mf32::create_scale(4.0, 9.0, 16.0)); - - assert!(!s1.is_2d()); - assert_eq!(Mf32::create_scale(2.0, 3.0, 0.0).to_2d(), Transform2D::create_scale(2.0, 3.0)); - } - - #[test] - pub fn test_ortho() { - let (left, right, bottom, top) = (0.0f32, 1.0f32, 0.1f32, 1.0f32); - let (near, far) = (-1.0f32, 1.0f32); - let result = Mf32::ortho(left, right, bottom, top, near, far); - let expected = Mf32::row_major( - 2.0, 0.0, 0.0, 0.0, - 0.0, 2.22222222, 0.0, 0.0, - 0.0, 0.0, -1.0, 0.0, - -1.0, -1.22222222, -0.0, 1.0 - ); - assert!(result.approx_eq(&expected)); - } - - #[test] - pub fn test_is_2d() { - assert!(Mf32::identity().is_2d()); - assert!(Mf32::create_rotation(0.0, 0.0, 1.0, rad(0.7854)).is_2d()); - assert!(!Mf32::create_rotation(0.0, 1.0, 0.0, rad(0.7854)).is_2d()); - } - - #[test] - pub fn test_row_major_2d() { - let m1 = Mf32::row_major_2d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); - let m2 = Mf32::row_major( - 1.0, 2.0, 0.0, 0.0, - 3.0, 4.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 5.0, 6.0, 0.0, 1.0 - ); - assert_eq!(m1, m2); - } - - #[test] - fn test_column_major() { - assert_eq!( - Mf32::row_major( - 1.0, 2.0, 3.0, 4.0, - 5.0, 6.0, 7.0, 8.0, - 9.0, 10.0, 11.0, 12.0, - 13.0, 14.0, 15.0, 16.0, - ), - Mf32::column_major( - 1.0, 5.0, 9.0, 13.0, - 2.0, 6.0, 10.0, 14.0, - 3.0, 7.0, 11.0, 15.0, - 4.0, 8.0, 12.0, 16.0, - ) - ); - } - - #[test] - pub fn test_inverse_simple() { - let m1 = Mf32::identity(); - let m2 = m1.inverse().unwrap(); - assert!(m1.approx_eq(&m2)); - } - - #[test] - pub fn test_inverse_scale() { - let m1 = Mf32::create_scale(1.5, 0.3, 2.1); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity())); - } - - #[test] - pub fn test_inverse_translate() { - let m1 = Mf32::create_translation(-132.0, 0.3, 493.0); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity())); - } - - #[test] - pub fn test_inverse_rotate() { - let m1 = Mf32::create_rotation(0.0, 1.0, 0.0, rad(1.57)); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity())); - } - - #[test] - pub fn test_inverse_transform_point_2d() { - let m1 = Mf32::create_translation(100.0, 200.0, 0.0); - let m2 = m1.inverse().unwrap(); - assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity())); - - let p1 = point2(1000.0, 2000.0); - let p2 = m1.transform_point2d(&p1); - assert!(p2.eq(&point2(1100.0, 2200.0))); - - let p3 = m2.transform_point2d(&p2); - assert!(p3.eq(&p1)); - } - - #[test] - fn test_inverse_none() { - assert!(Mf32::create_scale(2.0, 0.0, 2.0).inverse().is_none()); - assert!(Mf32::create_scale(2.0, 2.0, 2.0).inverse().is_some()); - } - - #[test] - pub fn test_pre_post() { - let m1 = Transform3D::identity().post_scale(1.0, 2.0, 3.0).post_translate(vec3(1.0, 2.0, 3.0)); - let m2 = Transform3D::identity().pre_translate(vec3(1.0, 2.0, 3.0)).pre_scale(1.0, 2.0, 3.0); - assert!(m1.approx_eq(&m2)); - - let r = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2)); - let t = Mf32::create_translation(2.0, 3.0, 0.0); - - let a = point3(1.0, 1.0, 1.0); - - assert!(r.post_mul(&t).transform_point3d(&a).approx_eq(&point3(3.0, 2.0, 1.0))); - assert!(t.post_mul(&r).transform_point3d(&a).approx_eq(&point3(4.0, -3.0, 1.0))); - assert!(t.post_mul(&r).transform_point3d(&a).approx_eq(&r.transform_point3d(&t.transform_point3d(&a)))); - - assert!(r.pre_mul(&t).transform_point3d(&a).approx_eq(&point3(4.0, -3.0, 1.0))); - assert!(t.pre_mul(&r).transform_point3d(&a).approx_eq(&point3(3.0, 2.0, 1.0))); - assert!(t.pre_mul(&r).transform_point3d(&a).approx_eq(&t.transform_point3d(&r.transform_point3d(&a)))); - } - - #[test] - fn test_size_of() { - use std::mem::size_of; - assert_eq!(size_of::>(), 16*size_of::()); - assert_eq!(size_of::>(), 16*size_of::()); - } - - #[test] - pub fn test_transform_associativity() { - let m1 = Mf32::row_major(3.0, 2.0, 1.5, 1.0, - 0.0, 4.5, -1.0, -4.0, - 0.0, 3.5, 2.5, 40.0, - 0.0, 3.0, 0.0, 1.0); - let m2 = Mf32::row_major(1.0, -1.0, 3.0, 0.0, - -1.0, 0.5, 0.0, 2.0, - 1.5, -2.0, 6.0, 0.0, - -2.5, 6.0, 1.0, 1.0); - - let p = point3(1.0, 3.0, 5.0); - let p1 = m2.pre_mul(&m1).transform_point3d(&p); - let p2 = m2.transform_point3d(&m1.transform_point3d(&p)); - assert!(p1.approx_eq(&p2)); - } - - #[test] - pub fn test_is_identity() { - let m1 = Transform3D::identity(); - assert!(m1.is_identity()); - let m2 = m1.post_translate(vec3(0.1, 0.0, 0.0)); - assert!(!m2.is_identity()); - } - - #[test] - pub fn test_transform_vector() { - // Translation does not apply to vectors. - let m = Mf32::create_translation(1.0, 2.0, 3.0); - let v1 = vec3(10.0, -10.0, 3.0); - assert_eq!(v1, m.transform_vector3d(&v1)); - // While it does apply to points. - assert!(v1.to_point() != m.transform_point3d(&v1.to_point())); - - // same thing with 2d vectors/points - let v2 = vec2(10.0, -5.0); - assert_eq!(v2, m.transform_vector2d(&v2)); - assert!(v2.to_point() != m.transform_point2d(&v2.to_point())); - } - - #[test] - pub fn test_is_backface_visible() { - // backface is not visible for rotate-x 0 degree. - let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(0.0)); - assert!(!r1.is_backface_visible()); - // backface is not visible for rotate-x 45 degree. - let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI * 0.25)); - assert!(!r1.is_backface_visible()); - // backface is visible for rotate-x 180 degree. - let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI)); - assert!(r1.is_backface_visible()); - // backface is visible for rotate-x 225 degree. - let r1 = Mf32::create_rotation(1.0, 0.0, 0.0, rad(PI * 1.25)); - assert!(r1.is_backface_visible()); - // backface is not visible for non-inverseable matrix - let r1 = Mf32::create_scale(2.0, 0.0, 2.0); - assert!(!r1.is_backface_visible()); - } - - #[test] - pub fn test_homogeneous() { - let m = Mf32::row_major( - 1.0, 2.0, 0.5, 5.0, - 3.0, 4.0, 0.25, 6.0, - 0.5, -1.0, 1.0, -1.0, - -1.0, 1.0, -1.0, 2.0, - ); - assert_eq!( - m.transform_point2d_homogeneous(&point2(1.0, 2.0)), - HomogeneousVector::new(6.0, 11.0, 0.0, 19.0), - ); - assert_eq!( - m.transform_point3d_homogeneous(&point3(1.0, 2.0, 4.0)), - HomogeneousVector::new(8.0, 7.0, 4.0, 15.0), - ); - } -} diff --git a/third_party/rust/euclid-0.17.3/src/trig.rs b/third_party/rust/euclid-0.17.3/src/trig.rs deleted file mode 100644 index 26ad5e951b8d..000000000000 --- a/third_party/rust/euclid-0.17.3/src/trig.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// Trait for basic trigonometry functions, so they can be used on generic numeric types -pub trait Trig { - fn sin(self) -> Self; - fn cos(self) -> Self; - fn tan(self) -> Self; - fn fast_atan2(y: Self, x: Self) -> Self; - fn degrees_to_radians(deg: Self) -> Self; - fn radians_to_degrees(rad: Self) -> Self; -} - -macro_rules! trig { - ($ty:ident) => ( - impl Trig for $ty { - #[inline] - fn sin(self) -> $ty { self.sin() } - #[inline] - fn cos(self) -> $ty { self.cos() } - #[inline] - fn tan(self) -> $ty { self.tan() } - - /// A slightly faster approximation of `atan2`. - /// - /// Note that it does not deal with the case where both x and y are 0. - #[inline] - fn fast_atan2(y: $ty, x: $ty) -> $ty { - // See https://math.stackexchange.com/questions/1098487/atan2-faster-approximation#1105038 - use std::$ty::consts; - let x_abs = x.abs(); - let y_abs = y.abs(); - let a = x_abs.min(y_abs) / x_abs.max(y_abs); - let s = a * a; - let mut result = ((-0.0464964749 * s + 0.15931422) * s - 0.327622764) * s * a + a; - if y_abs > x_abs { - result = consts::FRAC_PI_2 - result; - } - if x < 0.0 { - result = consts::PI - result - } - if y < 0.0 { - result = -result - } - - result - } - - #[inline] - fn degrees_to_radians(deg: Self) -> Self { - deg.to_radians() - } - - #[inline] - fn radians_to_degrees(rad: Self) -> Self { - rad.to_degrees() - } - } - ) -} - -trig!(f32); -trig!(f64); diff --git a/third_party/rust/euclid-0.17.3/src/vector.rs b/third_party/rust/euclid-0.17.3/src/vector.rs deleted file mode 100644 index cf13dc638d0f..000000000000 --- a/third_party/rust/euclid-0.17.3/src/vector.rs +++ /dev/null @@ -1,1417 +0,0 @@ -// Copyright 2013 The Servo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::UnknownUnit; -use approxeq::ApproxEq; -use length::Length; -use point::{TypedPoint2D, TypedPoint3D, point2, point3}; -use size::{TypedSize2D, size2}; -use scale::TypedScale; -use trig::Trig; -use Angle; -use num::*; -use num_traits::{Float, NumCast, Signed}; -use std::fmt; -use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use std::marker::PhantomData; - -define_matrix! { - /// A 2d Vector tagged with a unit. - pub struct TypedVector2D { - pub x: T, - pub y: T, - } -} - -/// Default 2d vector type with no unit. -/// -/// `Vector2D` provides the same methods as `TypedVector2D`. -pub type Vector2D = TypedVector2D; - -impl TypedVector2D { - /// Constructor, setting all components to zero. - #[inline] - pub fn zero() -> Self { - TypedVector2D::new(Zero::zero(), Zero::zero()) - } - - /// Convert into a 3d vector. - #[inline] - pub fn to_3d(&self) -> TypedVector3D { - vec3(self.x, self.y, Zero::zero()) - } -} - -impl fmt::Debug for TypedVector2D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?},{:?})", self.x, self.y) - } -} - -impl fmt::Display for TypedVector2D { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "({},{})", self.x, self.y) - } -} - -impl TypedVector2D { - /// Constructor taking scalar values directly. - #[inline] - pub fn new(x: T, y: T) -> Self { - TypedVector2D { - x: x, - y: y, - _unit: PhantomData, - } - } -} - -impl TypedVector2D { - /// Constructor taking properly typed Lengths instead of scalar values. - #[inline] - pub fn from_lengths(x: Length, y: Length) -> Self { - vec2(x.0, y.0) - } - - /// Create a 3d vector from this one, using the specified z value. - #[inline] - pub fn extend(&self, z: T) -> TypedVector3D { - vec3(self.x, self.y, z) - } - - /// Cast this vector into a point. - /// - /// Equivalent to adding this vector to the origin. - #[inline] - pub fn to_point(&self) -> TypedPoint2D { - point2(self.x, self.y) - } - - /// Swap x and y. - #[inline] - pub fn yx(&self) -> Self { - vec2(self.y, self.x) - } - - /// Cast this vector into a size. - #[inline] - pub fn to_size(&self) -> TypedSize2D { - size2(self.x, self.y) - } - - /// Returns self.x as a Length carrying the unit. - #[inline] - pub fn x_typed(&self) -> Length { - Length::new(self.x) - } - - /// Returns self.y as a Length carrying the unit. - #[inline] - pub fn y_typed(&self) -> Length { - Length::new(self.y) - } - - /// Drop the units, preserving only the numeric value. - #[inline] - pub fn to_untyped(&self) -> Vector2D { - vec2(self.x, self.y) - } - - /// Tag a unit-less value with units. - #[inline] - pub fn from_untyped(p: &Vector2D) -> Self { - vec2(p.x, p.y) - } - - #[inline] - pub fn to_array(&self) -> [T; 2] { - [self.x, self.y] - } -} - -impl TypedVector2D -where - T: Trig + Copy + Sub, -{ - /// Returns the angle between this vector and the x axis between -PI and PI. - pub fn angle_from_x_axis(&self) -> Angle { - Angle::radians(Trig::fast_atan2(self.y, self.x)) - } -} - -impl TypedVector2D -where - T: Copy + Mul + Add + Sub, -{ - /// Dot product. - #[inline] - pub fn dot(self, other: Self) -> T { - self.x * other.x + self.y * other.y - } - - /// Returns the norm of the cross product [self.x, self.y, 0] x [other.x, other.y, 0].. - #[inline] - pub fn cross(self, other: Self) -> T { - self.x * other.y - self.y * other.x - } - - #[inline] - pub fn normalize(self) -> Self - where - T: Float, - { - self / self.length() - } - - #[inline] - pub fn square_length(&self) -> T { - self.x * self.x + self.y * self.y - } - - #[inline] - pub fn length(&self) -> T - where - T: Float, - { - self.square_length().sqrt() - } -} - -impl TypedVector2D -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this vector and another vector. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - (*self) * one_t + other * t - } -} - -impl, U> Add for TypedVector2D { - type Output = Self; - fn add(self, other: Self) -> Self { - TypedVector2D::new(self.x + other.x, self.y + other.y) - } -} - -impl, U> AddAssign for TypedVector2D { - #[inline] - fn add_assign(&mut self, other: Self) { - *self = *self + other - } -} - -impl, U> SubAssign> for TypedVector2D { - #[inline] - fn sub_assign(&mut self, other: Self) { - *self = *self - other - } -} - -impl, U> Sub for TypedVector2D { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - vec2(self.x - other.x, self.y - other.y) - } -} - -impl, U> Neg for TypedVector2D { - type Output = Self; - #[inline] - fn neg(self) -> Self { - vec2(-self.x, -self.y) - } -} - -impl TypedVector2D { - #[inline] - pub fn min(self, other: Self) -> Self { - vec2(self.x.min(other.x), self.y.min(other.y)) - } - - #[inline] - pub fn max(self, other: Self) -> Self { - vec2(self.x.max(other.x), self.y.max(other.y)) - } -} - -impl, U> Mul for TypedVector2D { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - vec2(self.x * scale, self.y * scale) - } -} - -impl, U> Div for TypedVector2D { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - vec2(self.x / scale, self.y / scale) - } -} - -impl, U> MulAssign for TypedVector2D { - #[inline] - fn mul_assign(&mut self, scale: T) { - *self = *self * scale - } -} - -impl, U> DivAssign for TypedVector2D { - #[inline] - fn div_assign(&mut self, scale: T) { - *self = *self / scale - } -} - -impl, U1, U2> Mul> for TypedVector2D { - type Output = TypedVector2D; - #[inline] - fn mul(self, scale: TypedScale) -> Self::Output { - vec2(self.x * scale.get(), self.y * scale.get()) - } -} - -impl, U1, U2> Div> for TypedVector2D { - type Output = TypedVector2D; - #[inline] - fn div(self, scale: TypedScale) -> Self::Output { - vec2(self.x / scale.get(), self.y / scale.get()) - } -} - -impl TypedVector2D { - /// Rounds each component to the nearest integer value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.round() == { 0.0, -1.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn round(&self) -> Self { - vec2(self.x.round(), self.y.round()) - } -} - -impl TypedVector2D { - /// Rounds each component to the smallest integer equal or greater than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.ceil() == { 0.0, 0.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn ceil(&self) -> Self { - vec2(self.x.ceil(), self.y.ceil()) - } -} - -impl TypedVector2D { - /// Rounds each component to the biggest integer equal or lower than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - /// For example `{ -0.1, -0.8 }.floor() == { -1.0, -1.0 }`. - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn floor(&self) -> Self { - vec2(self.x.floor(), self.y.floor()) - } -} - -impl TypedVector2D { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating vector to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. - #[inline] - pub fn cast(&self) -> Option> { - match (NumCast::from(self.x), NumCast::from(self.y)) { - (Some(x), Some(y)) => Some(TypedVector2D::new(x, y)), - _ => None, - } - } - - // Convenience functions for common casts - - /// Cast into an `f32` vector. - #[inline] - pub fn to_f32(&self) -> TypedVector2D { - self.cast().unwrap() - } - - /// Cast into an `f64` vector. - #[inline] - pub fn to_f64(&self) -> TypedVector2D { - self.cast().unwrap() - } - - /// Cast into an `usize` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_usize(&self) -> TypedVector2D { - self.cast().unwrap() - } - - /// Cast into an `u32` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_u32(&self) -> TypedVector2D { - self.cast().unwrap() - } - - /// Cast into an i32 vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i32(&self) -> TypedVector2D { - self.cast().unwrap() - } - - /// Cast into an i64 vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i64(&self) -> TypedVector2D { - self.cast().unwrap() - } -} - -impl, U> ApproxEq> for TypedVector2D { - #[inline] - fn approx_epsilon() -> Self { - vec2(T::approx_epsilon(), T::approx_epsilon()) - } - - #[inline] - fn approx_eq(&self, other: &Self) -> bool { - self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) - } - - #[inline] - fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool { - self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y) - } -} - -impl Into<[T; 2]> for TypedVector2D { - fn into(self) -> [T; 2] { - self.to_array() - } -} - -impl From<[T; 2]> for TypedVector2D { - fn from(array: [T; 2]) -> Self { - vec2(array[0], array[1]) - } -} - -impl TypedVector2D -where - T: Signed, -{ - pub fn abs(&self) -> Self { - vec2(self.x.abs(), self.y.abs()) - } -} - -define_matrix! { - /// A 3d Vector tagged with a unit. - pub struct TypedVector3D { - pub x: T, - pub y: T, - pub z: T, - } -} - -/// Default 3d vector type with no unit. -/// -/// `Vector3D` provides the same methods as `TypedVector3D`. -pub type Vector3D = TypedVector3D; - -impl TypedVector3D { - /// Constructor, setting all components to zero. - #[inline] - pub fn zero() -> Self { - vec3(Zero::zero(), Zero::zero(), Zero::zero()) - } - - #[inline] - pub fn to_array_4d(&self) -> [T; 4] { - [self.x, self.y, self.z, Zero::zero()] - } -} - -impl fmt::Debug for TypedVector3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({:?},{:?},{:?})", self.x, self.y, self.z) - } -} - -impl fmt::Display for TypedVector3D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "({},{},{})", self.x, self.y, self.z) - } -} - -impl TypedVector3D { - /// Constructor taking scalar values directly. - #[inline] - pub fn new(x: T, y: T, z: T) -> Self { - TypedVector3D { - x: x, - y: y, - z: z, - _unit: PhantomData, - } - } -} - -impl TypedVector3D { - /// Constructor taking properly typed Lengths instead of scalar values. - #[inline] - pub fn from_lengths(x: Length, y: Length, z: Length) -> TypedVector3D { - vec3(x.0, y.0, z.0) - } - - /// Cast this vector into a point. - /// - /// Equivalent to adding this vector to the origin. - #[inline] - pub fn to_point(&self) -> TypedPoint3D { - point3(self.x, self.y, self.z) - } - - /// Returns a 2d vector using this vector's x and y coordinates - #[inline] - pub fn xy(&self) -> TypedVector2D { - vec2(self.x, self.y) - } - - /// Returns a 2d vector using this vector's x and z coordinates - #[inline] - pub fn xz(&self) -> TypedVector2D { - vec2(self.x, self.z) - } - - /// Returns a 2d vector using this vector's x and z coordinates - #[inline] - pub fn yz(&self) -> TypedVector2D { - vec2(self.y, self.z) - } - - /// Returns self.x as a Length carrying the unit. - #[inline] - pub fn x_typed(&self) -> Length { - Length::new(self.x) - } - - /// Returns self.y as a Length carrying the unit. - #[inline] - pub fn y_typed(&self) -> Length { - Length::new(self.y) - } - - /// Returns self.z as a Length carrying the unit. - #[inline] - pub fn z_typed(&self) -> Length { - Length::new(self.z) - } - - #[inline] - pub fn to_array(&self) -> [T; 3] { - [self.x, self.y, self.z] - } - - /// Drop the units, preserving only the numeric value. - #[inline] - pub fn to_untyped(&self) -> Vector3D { - vec3(self.x, self.y, self.z) - } - - /// Tag a unitless value with units. - #[inline] - pub fn from_untyped(p: &Vector3D) -> Self { - vec3(p.x, p.y, p.z) - } - - /// Convert into a 2d vector. - #[inline] - pub fn to_2d(&self) -> TypedVector2D { - self.xy() - } -} - -impl + Add + Sub + Copy, U> - TypedVector3D { - // Dot product. - #[inline] - pub fn dot(self, other: Self) -> T { - self.x * other.x + self.y * other.y + self.z * other.z - } - - // Cross product. - #[inline] - pub fn cross(self, other: Self) -> Self { - vec3( - self.y * other.z - self.z * other.y, - self.z * other.x - self.x * other.z, - self.x * other.y - self.y * other.x, - ) - } - - #[inline] - pub fn normalize(self) -> Self - where - T: Float, - { - self / self.length() - } - - #[inline] - pub fn square_length(&self) -> T { - self.x * self.x + self.y * self.y + self.z * self.z - } - - #[inline] - pub fn length(&self) -> T - where - T: Float, - { - self.square_length().sqrt() - } -} - -impl TypedVector3D -where - T: Copy + One + Add + Sub + Mul, -{ - /// Linearly interpolate between this vector and another vector. - /// - /// `t` is expected to be between zero and one. - #[inline] - pub fn lerp(&self, other: Self, t: T) -> Self { - let one_t = T::one() - t; - (*self) * one_t + other * t - } -} - -impl, U> Add for TypedVector3D { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - vec3(self.x + other.x, self.y + other.y, self.z + other.z) - } -} - -impl, U> Sub for TypedVector3D { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - vec3(self.x - other.x, self.y - other.y, self.z - other.z) - } -} - -impl, U> AddAssign for TypedVector3D { - #[inline] - fn add_assign(&mut self, other: Self) { - *self = *self + other - } -} - -impl, U> SubAssign> for TypedVector3D { - #[inline] - fn sub_assign(&mut self, other: Self) { - *self = *self - other - } -} - -impl, U> Neg for TypedVector3D { - type Output = Self; - #[inline] - fn neg(self) -> Self { - vec3(-self.x, -self.y, -self.z) - } -} - -impl, U> Mul for TypedVector3D { - type Output = Self; - #[inline] - fn mul(self, scale: T) -> Self { - Self::new(self.x * scale, self.y * scale, self.z * scale) - } -} - -impl, U> Div for TypedVector3D { - type Output = Self; - #[inline] - fn div(self, scale: T) -> Self { - Self::new(self.x / scale, self.y / scale, self.z / scale) - } -} - -impl, U> MulAssign for TypedVector3D { - #[inline] - fn mul_assign(&mut self, scale: T) { - *self = *self * scale - } -} - -impl, U> DivAssign for TypedVector3D { - #[inline] - fn div_assign(&mut self, scale: T) { - *self = *self / scale - } -} - -impl TypedVector3D { - #[inline] - pub fn min(self, other: Self) -> Self { - vec3( - self.x.min(other.x), - self.y.min(other.y), - self.z.min(other.z), - ) - } - - #[inline] - pub fn max(self, other: Self) -> Self { - vec3( - self.x.max(other.x), - self.y.max(other.y), - self.z.max(other.z), - ) - } -} - -impl, U1, U2> Mul> for TypedVector3D { - type Output = TypedVector3D; - #[inline] - fn mul(self, scale: TypedScale) -> Self::Output { - vec3(self.x * scale.get(), self.y * scale.get(), self.z * scale.get()) - } -} - -impl, U1, U2> Div> for TypedVector3D { - type Output = TypedVector3D; - #[inline] - fn div(self, scale: TypedScale) -> Self::Output { - vec3(self.x / scale.get(), self.y / scale.get(), self.z / scale.get()) - } -} - -impl TypedVector3D { - /// Rounds each component to the nearest integer value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn round(&self) -> Self { - vec3(self.x.round(), self.y.round(), self.z.round()) - } -} - -impl TypedVector3D { - /// Rounds each component to the smallest integer equal or greater than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn ceil(&self) -> Self { - vec3(self.x.ceil(), self.y.ceil(), self.z.ceil()) - } -} - -impl TypedVector3D { - /// Rounds each component to the biggest integer equal or lower than the original value. - /// - /// This behavior is preserved for negative values (unlike the basic cast). - #[inline] - #[cfg_attr(feature = "unstable", must_use)] - pub fn floor(&self) -> Self { - vec3(self.x.floor(), self.y.floor(), self.z.floor()) - } -} - -impl TypedVector3D { - /// Cast from one numeric representation to another, preserving the units. - /// - /// When casting from floating vector to integer coordinates, the decimals are truncated - /// as one would expect from a simple cast, but this behavior does not always make sense - /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. - #[inline] - pub fn cast(&self) -> Option> { - match ( - NumCast::from(self.x), - NumCast::from(self.y), - NumCast::from(self.z), - ) { - (Some(x), Some(y), Some(z)) => Some(vec3(x, y, z)), - _ => None, - } - } - - // Convenience functions for common casts - - /// Cast into an `f32` vector. - #[inline] - pub fn to_f32(&self) -> TypedVector3D { - self.cast().unwrap() - } - - /// Cast into an `f64` vector. - #[inline] - pub fn to_f64(&self) -> TypedVector3D { - self.cast().unwrap() - } - - /// Cast into an `usize` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_usize(&self) -> TypedVector3D { - self.cast().unwrap() - } - - /// Cast into an `u32` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_u32(&self) -> TypedVector3D { - self.cast().unwrap() - } - - /// Cast into an `i32` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i32(&self) -> TypedVector3D { - self.cast().unwrap() - } - - /// Cast into an `i64` vector, truncating decimals if any. - /// - /// When casting from floating vector vectors, it is worth considering whether - /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain - /// the desired conversion behavior. - #[inline] - pub fn to_i64(&self) -> TypedVector3D { - self.cast().unwrap() - } -} - -impl, U> ApproxEq> for TypedVector3D { - #[inline] - fn approx_epsilon() -> Self { - vec3( - T::approx_epsilon(), - T::approx_epsilon(), - T::approx_epsilon(), - ) - } - - #[inline] - fn approx_eq(&self, other: &Self) -> bool { - self.x.approx_eq(&other.x) && self.y.approx_eq(&other.y) && self.z.approx_eq(&other.z) - } - - #[inline] - fn approx_eq_eps(&self, other: &Self, eps: &Self) -> bool { - self.x.approx_eq_eps(&other.x, &eps.x) && self.y.approx_eq_eps(&other.y, &eps.y) - && self.z.approx_eq_eps(&other.z, &eps.z) - } -} - -impl Into<[T; 3]> for TypedVector3D { - fn into(self) -> [T; 3] { - self.to_array() - } -} - -impl From<[T; 3]> for TypedVector3D { - fn from(array: [T; 3]) -> Self { - vec3(array[0], array[1], array[2]) - } -} - -impl TypedVector3D -where - T: Signed, -{ - pub fn abs(&self) -> Self { - vec3(self.x.abs(), self.y.abs(), self.z.abs()) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct BoolVector2D { - pub x: bool, - pub y: bool, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct BoolVector3D { - pub x: bool, - pub y: bool, - pub z: bool, -} - -impl BoolVector2D { - #[inline] - pub fn all(&self) -> bool { - self.x && self.y - } - - #[inline] - pub fn any(&self) -> bool { - self.x || self.y - } - - #[inline] - pub fn none(&self) -> bool { - !self.any() - } - - #[inline] - pub fn and(&self, other: Self) -> Self { - BoolVector2D { - x: self.x && other.x, - y: self.y && other.y, - } - } - - #[inline] - pub fn or(&self, other: Self) -> Self { - BoolVector2D { - x: self.x || other.x, - y: self.y || other.y, - } - } - - #[inline] - pub fn not(&self) -> Self { - BoolVector2D { - x: !self.x, - y: !self.y, - } - } - - #[inline] - pub fn select_point(&self, a: &TypedPoint2D, b: &TypedPoint2D) -> TypedPoint2D { - point2( - if self.x { a.x } else { b.x }, - if self.y { a.y } else { b.y }, - ) - } - - #[inline] - pub fn select_vector(&self, a: &TypedVector2D, b: &TypedVector2D) -> TypedVector2D { - vec2( - if self.x { a.x } else { b.x }, - if self.y { a.y } else { b.y }, - ) - } - - #[inline] - pub fn select_size(&self, a: &TypedSize2D, b: &TypedSize2D) -> TypedSize2D { - size2( - if self.x { a.width } else { b.width }, - if self.y { a.height } else { b.height }, - ) - } -} - -impl BoolVector3D { - #[inline] - pub fn all(&self) -> bool { - self.x && self.y && self.z - } - - #[inline] - pub fn any(&self) -> bool { - self.x || self.y || self.z - } - - #[inline] - pub fn none(&self) -> bool { - !self.any() - } - - #[inline] - pub fn and(&self, other: Self) -> Self { - BoolVector3D { - x: self.x && other.x, - y: self.y && other.y, - z: self.z && other.z, - } - } - - #[inline] - pub fn or(&self, other: Self) -> Self { - BoolVector3D { - x: self.x || other.x, - y: self.y || other.y, - z: self.z || other.z, - } - } - - #[inline] - pub fn not(&self) -> Self { - BoolVector3D { - x: !self.x, - y: !self.y, - z: !self.z, - } - } - - - #[inline] - pub fn select_point(&self, a: &TypedPoint3D, b: &TypedPoint3D) -> TypedPoint3D { - point3( - if self.x { a.x } else { b.x }, - if self.y { a.y } else { b.y }, - if self.z { a.z } else { b.z }, - ) - } - - #[inline] - pub fn select_vector(&self, a: &TypedVector3D, b: &TypedVector3D) -> TypedVector3D { - vec3( - if self.x { a.x } else { b.x }, - if self.y { a.y } else { b.y }, - if self.z { a.z } else { b.z }, - ) - } - - #[inline] - pub fn xy(&self) -> BoolVector2D { - BoolVector2D { - x: self.x, - y: self.y, - } - } - - #[inline] - pub fn xz(&self) -> BoolVector2D { - BoolVector2D { - x: self.x, - y: self.z, - } - } - - #[inline] - pub fn yz(&self) -> BoolVector2D { - BoolVector2D { - x: self.y, - y: self.z, - } - } -} - -impl TypedVector2D { - pub fn greater_than(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.x > other.x, - y: self.y > other.y, - } - } - - pub fn lower_than(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.x < other.x, - y: self.y < other.y, - } - } -} - - -impl TypedVector2D { - pub fn equal(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.x == other.x, - y: self.y == other.y, - } - } - - pub fn not_equal(&self, other: &Self) -> BoolVector2D { - BoolVector2D { - x: self.x != other.x, - y: self.y != other.y, - } - } -} - -impl TypedVector3D { - pub fn greater_than(&self, other: &Self) -> BoolVector3D { - BoolVector3D { - x: self.x > other.x, - y: self.y > other.y, - z: self.z > other.z, - } - } - - pub fn lower_than(&self, other: &Self) -> BoolVector3D { - BoolVector3D { - x: self.x < other.x, - y: self.y < other.y, - z: self.z < other.z, - } - } -} - - -impl TypedVector3D { - pub fn equal(&self, other: &Self) -> BoolVector3D { - BoolVector3D { - x: self.x == other.x, - y: self.y == other.y, - z: self.z == other.z, - } - } - - pub fn not_equal(&self, other: &Self) -> BoolVector3D { - BoolVector3D { - x: self.x != other.x, - y: self.y != other.y, - z: self.z != other.z, - } - } -} - -/// Convenience constructor. -#[inline] -pub fn vec2(x: T, y: T) -> TypedVector2D { - TypedVector2D::new(x, y) -} - -/// Convenience constructor. -#[inline] -pub fn vec3(x: T, y: T, z: T) -> TypedVector3D { - TypedVector3D::new(x, y, z) -} - -#[inline] -pub fn bvec2(x: bool, y: bool) -> BoolVector2D { - BoolVector2D { x, y } -} - -#[inline] -pub fn bvec3(x: bool, y: bool, z: bool) -> BoolVector3D { - BoolVector3D { x, y, z } -} - - -#[cfg(test)] -mod vector2d { - use super::{Vector2D, vec2}; - type Vec2 = Vector2D; - - #[test] - pub fn test_scalar_mul() { - let p1: Vec2 = vec2(3.0, 5.0); - - let result = p1 * 5.0; - - assert_eq!(result, Vector2D::new(15.0, 25.0)); - } - - #[test] - pub fn test_dot() { - let p1: Vec2 = vec2(2.0, 7.0); - let p2: Vec2 = vec2(13.0, 11.0); - assert_eq!(p1.dot(p2), 103.0); - } - - #[test] - pub fn test_cross() { - let p1: Vec2 = vec2(4.0, 7.0); - let p2: Vec2 = vec2(13.0, 8.0); - let r = p1.cross(p2); - assert_eq!(r, -59.0); - } - - #[test] - pub fn test_normalize() { - let p0: Vec2 = Vec2::zero(); - let p1: Vec2 = vec2(4.0, 0.0); - let p2: Vec2 = vec2(3.0, -4.0); - assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan()); - assert_eq!(p1.normalize(), vec2(1.0, 0.0)); - assert_eq!(p2.normalize(), vec2(0.6, -0.8)); - } - - #[test] - pub fn test_min() { - let p1: Vec2 = vec2(1.0, 3.0); - let p2: Vec2 = vec2(2.0, 2.0); - - let result = p1.min(p2); - - assert_eq!(result, vec2(1.0, 2.0)); - } - - #[test] - pub fn test_max() { - let p1: Vec2 = vec2(1.0, 3.0); - let p2: Vec2 = vec2(2.0, 2.0); - - let result = p1.max(p2); - - assert_eq!(result, vec2(2.0, 3.0)); - } - - #[test] - pub fn test_angle_from_x_axis() { - use std::f32::consts::FRAC_PI_2; - use approxeq::ApproxEq; - - let right: Vec2 = vec2(10.0, 0.0); - let down: Vec2 = vec2(0.0, 4.0); - let up: Vec2 = vec2(0.0, -1.0); - - assert!(right.angle_from_x_axis().get().approx_eq(&0.0)); - assert!(down.angle_from_x_axis().get().approx_eq(&FRAC_PI_2)); - assert!(up.angle_from_x_axis().get().approx_eq(&-FRAC_PI_2)); - } -} - -#[cfg(test)] -mod typedvector2d { - use super::{TypedVector2D, Vector2D, vec2}; - use scale::TypedScale; - - pub enum Mm {} - pub enum Cm {} - - pub type Vector2DMm = TypedVector2D; - pub type Vector2DCm = TypedVector2D; - - #[test] - pub fn test_add() { - let p1 = Vector2DMm::new(1.0, 2.0); - let p2 = Vector2DMm::new(3.0, 4.0); - - let result = p1 + p2; - - assert_eq!(result, vec2(4.0, 6.0)); - } - - #[test] - pub fn test_add_assign() { - let mut p1 = Vector2DMm::new(1.0, 2.0); - p1 += vec2(3.0, 4.0); - - assert_eq!(p1, vec2(4.0, 6.0)); - } - - #[test] - pub fn test_scalar_mul() { - let p1 = Vector2DMm::new(1.0, 2.0); - let cm_per_mm = TypedScale::::new(0.1); - - let result: Vector2DCm = p1 * cm_per_mm; - - assert_eq!(result, vec2(0.1, 0.2)); - } - - #[test] - pub fn test_swizzling() { - let p: Vector2D = vec2(1, 2); - assert_eq!(p.yx(), vec2(2, 1)); - } -} - -#[cfg(test)] -mod vector3d { - use super::{TypedVector3D, Vector3D, vec2, vec3}; - use scale::TypedScale; - - type Vec3 = Vector3D; - - #[test] - pub fn test_dot() { - let p1: Vec3 = vec3(7.0, 21.0, 32.0); - let p2: Vec3 = vec3(43.0, 5.0, 16.0); - assert_eq!(p1.dot(p2), 918.0); - } - - #[test] - pub fn test_cross() { - let p1: Vec3 = vec3(4.0, 7.0, 9.0); - let p2: Vec3 = vec3(13.0, 8.0, 3.0); - let p3 = p1.cross(p2); - assert_eq!(p3, vec3(-51.0, 105.0, -59.0)); - } - - #[test] - pub fn test_normalize() { - let p0: Vec3 = Vec3::zero(); - let p1: Vec3 = vec3(0.0, -6.0, 0.0); - let p2: Vec3 = vec3(1.0, 2.0, -2.0); - assert!( - p0.normalize().x.is_nan() && p0.normalize().y.is_nan() && p0.normalize().z.is_nan() - ); - assert_eq!(p1.normalize(), vec3(0.0, -1.0, 0.0)); - assert_eq!(p2.normalize(), vec3(1.0 / 3.0, 2.0 / 3.0, -2.0 / 3.0)); - } - - #[test] - pub fn test_min() { - let p1: Vec3 = vec3(1.0, 3.0, 5.0); - let p2: Vec3 = vec3(2.0, 2.0, -1.0); - - let result = p1.min(p2); - - assert_eq!(result, vec3(1.0, 2.0, -1.0)); - } - - #[test] - pub fn test_max() { - let p1: Vec3 = vec3(1.0, 3.0, 5.0); - let p2: Vec3 = vec3(2.0, 2.0, -1.0); - - let result = p1.max(p2); - - assert_eq!(result, vec3(2.0, 3.0, 5.0)); - } - - #[test] - pub fn test_scalar_mul() { - enum Mm {} - enum Cm {} - - let p1 = TypedVector3D::::new(1.0, 2.0, 3.0); - let cm_per_mm = TypedScale::::new(0.1); - - let result: TypedVector3D = p1 * cm_per_mm; - - assert_eq!(result, vec3(0.1, 0.2, 0.3)); - } - - #[test] - pub fn test_swizzling() { - let p: Vector3D = vec3(1, 2, 3); - assert_eq!(p.xy(), vec2(1, 2)); - assert_eq!(p.xz(), vec2(1, 3)); - assert_eq!(p.yz(), vec2(2, 3)); - } -} - -mod bool_vector { - use super::*; - type Vec2 = Vector2D; - type Vec3 = Vector3D; - - #[test] - fn test_bvec2() { - - assert_eq!( - Vec2::new(1.0, 2.0).greater_than(&Vec2::new(2.0, 1.0)), - bvec2(false, true), - ); - - assert_eq!( - Vec2::new(1.0, 2.0).lower_than(&Vec2::new(2.0, 1.0)), - bvec2(true, false), - ); - - assert_eq!( - Vec2::new(1.0, 2.0).equal(&Vec2::new(1.0, 3.0)), - bvec2(true, false), - ); - - assert_eq!( - Vec2::new(1.0, 2.0).not_equal(&Vec2::new(1.0, 3.0)), - bvec2(false, true), - ); - - assert!(bvec2(true, true).any()); - assert!(bvec2(false, true).any()); - assert!(bvec2(true, false).any()); - assert!(!bvec2(false, false).any()); - assert!(bvec2(false, false).none()); - assert!(bvec2(true, true).all()); - assert!(!bvec2(false, true).all()); - assert!(!bvec2(true, false).all()); - assert!(!bvec2(false, false).all()); - - assert_eq!(bvec2(true, false).not(), bvec2(false, true)); - assert_eq!(bvec2(true, false).and(bvec2(true, true)), bvec2(true, false)); - assert_eq!(bvec2(true, false).or(bvec2(true, true)), bvec2(true, true)); - - assert_eq!( - bvec2(true, false).select_vector(&Vec2::new(1.0, 2.0), &Vec2::new(3.0, 4.0)), - Vec2::new(1.0, 4.0), - ); - } - - #[test] - fn test_bvec3() { - - assert_eq!( - Vec3::new(1.0, 2.0, 3.0).greater_than(&Vec3::new(3.0, 2.0, 1.0)), - bvec3(false, false, true), - ); - - assert_eq!( - Vec3::new(1.0, 2.0, 3.0).lower_than(&Vec3::new(3.0, 2.0, 1.0)), - bvec3(true, false, false), - ); - - assert_eq!( - Vec3::new(1.0, 2.0, 3.0).equal(&Vec3::new(3.0, 2.0, 1.0)), - bvec3(false, true, false), - ); - - assert_eq!( - Vec3::new(1.0, 2.0, 3.0).not_equal(&Vec3::new(3.0, 2.0, 1.0)), - bvec3(true, false, true), - ); - - assert!(bvec3(true, true, false).any()); - assert!(bvec3(false, true, false).any()); - assert!(bvec3(true, false, false).any()); - assert!(!bvec3(false, false, false).any()); - assert!(bvec3(false, false, false).none()); - assert!(bvec3(true, true, true).all()); - assert!(!bvec3(false, true, false).all()); - assert!(!bvec3(true, false, false).all()); - assert!(!bvec3(false, false, false).all()); - - assert_eq!(bvec3(true, false, true).not(), bvec3(false, true, false)); - assert_eq!(bvec3(true, false, true).and(bvec3(true, true, false)), bvec3(true, false, false)); - assert_eq!(bvec3(true, false, false).or(bvec3(true, true, false)), bvec3(true, true, false)); - - assert_eq!( - bvec3(true, false, true).select_vector(&Vec3::new(1.0, 2.0, 3.0), &Vec3::new(4.0, 5.0, 6.0)), - Vec3::new(1.0, 5.0, 3.0), - ); - } - -} \ No newline at end of file diff --git a/third_party/rust/gleam/.cargo-checksum.json b/third_party/rust/gleam/.cargo-checksum.json index 42e267dc4df9..14d5c3c15504 100644 --- a/third_party/rust/gleam/.cargo-checksum.json +++ b/third_party/rust/gleam/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".travis.yml":"29b74b95210896ce634c11a9037638668473b5a1b3b1716c505cb04dbb6341fa","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"96141412a2322a5dfe693d87d5792e7c9859340f751109856024b9870d2289d3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"a1616d76f35b3a6015c2ee22ecf13eb225095b22e4190ef5ef2fcd9197b43ad1","src/gl.rs":"0a2f631a09ddfa267d6dcf2274342529b6f487e1cb982b92e1111a64c1d7437e","src/gl_fns.rs":"ead6bbdc6a937264275e849ed84ab9b1be83624fcea31aa7bde2d933390ee151","src/gles_fns.rs":"ba64f9a124af370121ba526c262ccb0f87ebf6f99115fc25e2a9ae5a8d39af34","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"e47b39459e47b76be4d2c82702932cdc66df09dcb8f813424167991adb8b3380"} \ No newline at end of file +{"files":{".travis.yml":"29b74b95210896ce634c11a9037638668473b5a1b3b1716c505cb04dbb6341fa","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"07f8164277c2a586bae90fdc42d01d060cc54dbf8c62a2f3d7ba7871bbee20cb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"e155f5d7f71fe10d18e108fe6557f31ae5fec425a3acbdf564b02b0bc695fde4","src/gl.rs":"4b0fcc262883f226699769ef76611380bbfba1b56b762257b99be328195be4c5","src/gl_fns.rs":"58a8ab3e82d2d582874e95465ce44e0827d48f846668bc9620978d6748ea0255","src/gles_fns.rs":"4b1eb8eaacdd5514c3a93ab77403e4232d8a680452311c120b9340ab94a4a0b9","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"0d41e7ac812597988fdae31c9baec3c6d35cadb8ad9ab88a9bf9c0f119ed66c2"} \ No newline at end of file diff --git a/third_party/rust/gleam/Cargo.toml b/third_party/rust/gleam/Cargo.toml index 4c9eae61b0c9..113ecf3b5e6e 100644 --- a/third_party/rust/gleam/Cargo.toml +++ b/third_party/rust/gleam/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "gleam" -version = "0.5.0" +version = "0.6.0" authors = ["The Servo Project Developers"] build = "build.rs" description = "Generated OpenGL bindings and wrapper for Servo." diff --git a/third_party/rust/gleam/build.rs b/third_party/rust/gleam/build.rs index 638eb71d8580..336f936be4b4 100644 --- a/third_party/rust/gleam/build.rs +++ b/third_party/rust/gleam/build.rs @@ -13,13 +13,14 @@ fn main() { // OpenGL 3.3 bindings let gl_extensions = [ + "GL_APPLE_client_storage", + "GL_APPLE_fence", + "GL_APPLE_texture_range", + "GL_ARB_blend_func_extended", + "GL_ARB_get_program_binary", "GL_ARB_texture_rectangle", "GL_EXT_debug_marker", - "GL_APPLE_client_storage", - "GL_APPLE_texture_range", - "GL_APPLE_fence", - "GL_ARB_get_program_binary", - "GL_ARB_blend_func_extended", + "GL_EXT_texture_filter_anisotropic", "GL_KHR_debug", ]; let gl_reg = Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, gl_extensions); @@ -28,12 +29,14 @@ fn main() { // GLES 3.0 bindings let gles_extensions = [ - "GL_EXT_texture_format_BGRA8888", - "GL_OES_EGL_image", - "GL_OES_EGL_image_external", - "GL_EXT_disjoint_timer_query", "GL_EXT_debug_marker", + "GL_EXT_disjoint_timer_query", + "GL_EXT_shader_texture_lod", + "GL_EXT_texture_filter_anisotropic", + "GL_EXT_texture_format_BGRA8888", "GL_KHR_debug", + "GL_OES_EGL_image_external", + "GL_OES_EGL_image", ]; let gles_reg = Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, gles_extensions); gles_reg.write_bindings(gl_generator::StructGenerator, &mut file_gles) diff --git a/third_party/rust/gleam/src/gl.rs b/third_party/rust/gleam/src/gl.rs index fd0ef25f2de4..1cbe976b47e4 100644 --- a/third_party/rust/gleam/src/gl.rs +++ b/third_party/rust/gleam/src/gl.rs @@ -62,37 +62,6 @@ fn calculate_length(width: GLsizei, height: GLsizei, format: GLenum, pixel_type: return (width * height * colors * depth) as usize; } -// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 -fn get_uniform_iv_vector_length(uniform_type: &GLuint) -> usize { - match *uniform_type { - ffi::BOOL | - ffi::INT | - ffi::SAMPLER_2D | - ffi::SAMPLER_CUBE => 1, - ffi::INT_VEC2 | - ffi::BOOL_VEC2 => 2, - ffi::INT_VEC3 | - ffi::BOOL_VEC3 => 3, - ffi::INT_VEC4 | - ffi::BOOL_VEC4 => 4, - _ => panic!("Invalid location argument"), - } -} - -// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 -fn get_uniform_fv_vector_length(uniform_type: &GLuint) -> usize { - match *uniform_type { - ffi::FLOAT => 1, - ffi::FLOAT_VEC2 => 2, - ffi::FLOAT_VEC3 => 3, - ffi::FLOAT_VEC4 | - ffi::FLOAT_MAT2 => 4, - ffi::FLOAT_MAT3 => 9, - ffi::FLOAT_MAT4 => 16, - _ => panic!("Invalid location argument"), - } -} - pub struct DebugMessage { pub message: String, pub source: GLenum, @@ -185,8 +154,8 @@ declare_gl_apis! { fn active_texture(&self, texture: GLenum); fn attach_shader(&self, program: GLuint, shader: GLuint); fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str); - fn get_uniform_iv(&self, program: GLuint, location: GLint) -> Vec; - fn get_uniform_fv(&self, program: GLuint, location: GLint) -> Vec; + unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]); + unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]); fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint; fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec; fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint); diff --git a/third_party/rust/gleam/src/gl_fns.rs b/third_party/rust/gleam/src/gl_fns.rs index d82aafb289c8..4b314ebab186 100644 --- a/third_party/rust/gleam/src/gl_fns.rs +++ b/third_party/rust/gleam/src/gl_fns.rs @@ -19,21 +19,6 @@ impl GlFns ffi_gl_: ffi_gl_, }) as Rc } - - fn get_active_uniform_type(&self, program: GLuint) -> GLuint { - let mut size: GLint = 0; - let mut uniform_type: GLuint = 0; - unsafe { - self.ffi_gl_.GetActiveUniform(program, - 0 as GLuint, - 0 as GLsizei, - ptr::null_mut(), - &mut size, - &mut uniform_type, - ptr::null_mut()); - } - uniform_type - } } impl Gl for GlFns { @@ -309,25 +294,15 @@ impl Gl for GlFns { } // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml - fn get_uniform_iv(&self, program: GLuint, location: GLint) -> Vec { - let uniform_type = self.get_active_uniform_type(program); - let len = get_uniform_iv_vector_length(&uniform_type); - let mut result: [GLint; 4] = [0; 4]; - unsafe { - self.ffi_gl_.GetUniformiv(program, location, result.as_mut_ptr()); - } - Vec::from(&result[0..len]) + unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) { + assert!(!result.is_empty()); + self.ffi_gl_.GetUniformiv(program, location, result.as_mut_ptr()); } // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml - fn get_uniform_fv(&self, program: GLuint, location: GLint) -> Vec { - let uniform_type = self.get_active_uniform_type(program); - let len = get_uniform_fv_vector_length(&uniform_type); - let mut result: [GLfloat; 16] = [0.0; 16]; - unsafe { - self.ffi_gl_.GetUniformfv(program, location, result.as_mut_ptr()); - } - Vec::from(&result[0..len]) + unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) { + assert!(!result.is_empty()); + self.ffi_gl_.GetUniformfv(program, location, result.as_mut_ptr()); } fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { diff --git a/third_party/rust/gleam/src/gles_fns.rs b/third_party/rust/gleam/src/gles_fns.rs index 9bba68467f53..b2f3fd6747ef 100644 --- a/third_party/rust/gleam/src/gles_fns.rs +++ b/third_party/rust/gleam/src/gles_fns.rs @@ -19,21 +19,6 @@ impl GlesFns ffi_gl_: ffi_gl_, }) as Rc } - - fn get_active_uniform_type(&self, program: GLuint) -> GLuint { - let mut size: GLint = 0; - let mut uniform_type: GLuint = 0; - unsafe { - self.ffi_gl_.GetActiveUniform(program, - 0 as GLuint, - 0 as GLsizei, - ptr::null_mut(), - &mut size, - &mut uniform_type, - ptr::null_mut()); - } - uniform_type - } } impl Gl for GlesFns { @@ -333,25 +318,15 @@ impl Gl for GlesFns { } // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml - fn get_uniform_iv(&self, program: GLuint, location: GLint) -> Vec { - let uniform_type = self.get_active_uniform_type(program); - let len = get_uniform_iv_vector_length(&uniform_type); - let mut result: [GLint; 4] = [0; 4]; - unsafe { - self.ffi_gl_.GetUniformiv(program, location, result.as_mut_ptr()); - } - Vec::from(&result[0..len]) + unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) { + assert!(!result.is_empty()); + self.ffi_gl_.GetUniformiv(program, location, result.as_mut_ptr()); } // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml - fn get_uniform_fv(&self, program: GLuint, location: GLint) -> Vec { - let uniform_type = self.get_active_uniform_type(program); - let len = get_uniform_fv_vector_length(&uniform_type); - let mut result: [GLfloat; 16] = [0.0; 16]; - unsafe { - self.ffi_gl_.GetUniformfv(program, location, result.as_mut_ptr()); - } - Vec::from(&result[0..len]) + unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) { + assert!(!result.is_empty()); + self.ffi_gl_.GetUniformfv(program, location, result.as_mut_ptr()); } fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { diff --git a/third_party/rust/plane-split/.cargo-checksum.json b/third_party/rust/plane-split/.cargo-checksum.json index 2157c4f3f007..1723b6a9e080 100644 --- a/third_party/rust/plane-split/.cargo-checksum.json +++ b/third_party/rust/plane-split/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".travis.yml":"b76d49f66f842c652d40825c67791352364a6b6bbb7d8d1009f2ac79eb413e66","Cargo.toml":"8f2b69b8ed35600a4fc9543a17f07f4eb1332602a8c31f07f75d8c415465e6b3","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"98cd4982b1641146ac0a2bd4878a634768b94cbe2db7719bad30501e4ae8e82e","src/lib.rs":"ac7a25ea2f1543dc2b45decd3ec27e0c27dcc19c78bee8a3e0bbb3324e158d53","src/polygon.rs":"1c86fe39d10414c3cc7238ce2b1b22e7ce2aaa15cc931adecb5ef217ce861d50","tests/clip.rs":"606aff2a26a2054ed0dbd5377a356791440b5f88e6bf0c8447702cc5851fac4c","tests/main.rs":"182669f26ce9f88ff82a36669aaae22458fd20f997a54375d3748a150af3f51a","tests/split.rs":"ec57ecb682bcd1e1c059905f6b05b72f2ae86be3ce2a0e657058bb83c6cff68e"},"package":"7079b8485b4f9d9560dee7a69ca8f6ca781f9f284ff9d2bf27255d440b03e4af"} \ No newline at end of file +{"files":{".travis.yml":"b76d49f66f842c652d40825c67791352364a6b6bbb7d8d1009f2ac79eb413e66","Cargo.toml":"ee68f6bd7972f6918091b4557302bbb655327d822413ba09102c0e63b49502fb","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"98cd4982b1641146ac0a2bd4878a634768b94cbe2db7719bad30501e4ae8e82e","src/lib.rs":"ac7a25ea2f1543dc2b45decd3ec27e0c27dcc19c78bee8a3e0bbb3324e158d53","src/polygon.rs":"ee10d7ddc8369b964d548e53ad9cfa09d84a65b22e02ec2866175dc44469bb6e","tests/clip.rs":"606aff2a26a2054ed0dbd5377a356791440b5f88e6bf0c8447702cc5851fac4c","tests/main.rs":"c64d2d597a1f3c702921639a2af49c4a61ea6952b983a79749458c18c64eb69f","tests/split.rs":"0eb1afb1f26cdecd5fffbf32d57e889f8f69254c0a57eecb8ccbbdf38efcdf27"},"package":"6e14382aabad89085fbf714f75d527492bb672725facb9b2ced2fada47cf418c"} \ No newline at end of file diff --git a/third_party/rust/plane-split/Cargo.toml b/third_party/rust/plane-split/Cargo.toml index 781f1e011c78..82c22aa419b3 100644 --- a/third_party/rust/plane-split/Cargo.toml +++ b/third_party/rust/plane-split/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "plane-split" -version = "0.9.1" +version = "0.10.0" authors = ["Dzmitry Malyshau "] description = "Plane splitting" documentation = "https://docs.rs/plane-split" @@ -23,7 +23,7 @@ repository = "https://github.com/servo/plane-split" version = "0.1.2" [dependencies.euclid] -version = "0.17" +version = "0.18" [dependencies.log] version = "0.4" diff --git a/third_party/rust/plane-split/src/polygon.rs b/third_party/rust/plane-split/src/polygon.rs index f35e4ec02b8a..dc0741bd76cb 100644 --- a/third_party/rust/plane-split/src/polygon.rs +++ b/third_party/rust/plane-split/src/polygon.rs @@ -143,21 +143,21 @@ impl Polygon where rect: TypedRect, transform: TypedTransform3D, anchor: usize, - ) -> Self + ) -> Option where T: Trig + ops::Neg, { let points = [ - transform.transform_point3d(&rect.origin.to_3d()), - transform.transform_point3d(&rect.top_right().to_3d()), - transform.transform_point3d(&rect.bottom_right().to_3d()), - transform.transform_point3d(&rect.bottom_left().to_3d()), + transform.transform_point3d(&rect.origin.to_3d())?, + transform.transform_point3d(&rect.top_right().to_3d())?, + transform.transform_point3d(&rect.bottom_right().to_3d())?, + transform.transform_point3d(&rect.bottom_left().to_3d())?, ]; //Note: this code path could be more efficient if we had inverse-transpose //let n4 = transform.transform_point4d(&TypedPoint4D::new(T::zero(), T::zero(), T::one(), T::zero())); //let normal = TypedPoint3D::new(n4.x, n4.y, n4.z); - Self::from_points(points, anchor) + Some(Self::from_points(points, anchor)) } /// Bring a point into the local coordinate space, returning diff --git a/third_party/rust/plane-split/tests/main.rs b/third_party/rust/plane-split/tests/main.rs index 2e3276bd34e9..0eca18c9f414 100644 --- a/third_party/rust/plane-split/tests/main.rs +++ b/third_party/rust/plane-split/tests/main.rs @@ -65,7 +65,7 @@ fn from_transformed_rect() { TypedTransform3D::create_rotation(0.5f32.sqrt(), 0.0, 0.5f32.sqrt(), Angle::radians(5.0)) .pre_translate(vec3(0.0, 0.0, 10.0)); let poly = Polygon::from_transformed_rect(rect, transform, 0); - assert!(poly.is_valid()); + assert!(poly.is_some() && poly.unwrap().is_valid()); } #[test] diff --git a/third_party/rust/plane-split/tests/split.rs b/third_party/rust/plane-split/tests/split.rs index 472afdeb9298..adc61026b57a 100644 --- a/third_party/rust/plane-split/tests/split.rs +++ b/third_party/rust/plane-split/tests/split.rs @@ -27,12 +27,12 @@ fn sort_rotation(splitter: &mut Splitter) { TypedTransform3D::create_rotation(0.0, 1.0, 0.0, Angle::radians(FRAC_PI_4)); let rect: TypedRect = euclid::rect(-10.0, -10.0, 20.0, 20.0); - let polys = [ - Polygon::from_transformed_rect(rect, transform0, 0), - Polygon::from_transformed_rect(rect, transform1, 1), - Polygon::from_transformed_rect(rect, transform2, 2), - ]; + let p1 = Polygon::from_transformed_rect(rect, transform0, 0); + let p2 = Polygon::from_transformed_rect(rect, transform1, 1); + let p3 = Polygon::from_transformed_rect(rect, transform2, 2); + assert!(p1.is_some() && p2.is_some() && p3.is_some(), "Cannot construct transformed polygons"); + let polys = [ p1.unwrap(), p2.unwrap(), p3.unwrap() ]; let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0)); let ids: Vec<_> = result.iter().map(|poly| poly.anchor).collect(); assert_eq!(&ids, &[2, 1, 0, 1, 2]); @@ -49,7 +49,9 @@ fn sort_trivial(splitter: &mut Splitter) { let rect: TypedRect = euclid::rect(-10.0, -10.0, 20.0, 20.0); let polys: Vec<_> = anchors.iter().map(|&anchor| { let transform: TypedTransform3D = TypedTransform3D::create_translation(0.0, 0.0, anchor as f32); - Polygon::from_transformed_rect(rect, transform, anchor) + let poly = Polygon::from_transformed_rect(rect, transform, anchor); + assert!(poly.is_some(), "Cannot construct transformed polygons"); + poly.unwrap() }).collect(); let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0)); diff --git a/third_party/rust/smallvec/.cargo-checksum.json b/third_party/rust/smallvec/.cargo-checksum.json index a5768b623054..5327b0f784a1 100644 --- a/third_party/rust/smallvec/.cargo-checksum.json +++ b/third_party/rust/smallvec/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".travis.yml":"91edce5ea2a1956399db4b17f580c8b7995af3aa9801c4314865f560c55d6d09","Cargo.toml":"1bbfc40ffd7370696242dd27dd4f0e211d3309aebca8b564029a6ac167e81726","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"1bc64a621160a291c86b8770f3eeaa45a31c31d91c2a071f39981c14fdacb035","benches/bench.rs":"54cf4879d36ba2a9f3423af91bb93227b70849200e5bf74e384a166d6aa09893","lib.rs":"bd237262110649b266c6599d4f8b3d1f7d7c758d6852b65243c8221811d273e8"},"package":"44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"} \ No newline at end of file +{"files":{".travis.yml":"1fb562c82e3ba8668667016eb5be043130a943a3e22c2c692dfcefd23bb07028","Cargo.toml":"2f8fa5e2e7894727dab3b256f93c739ee2fdd715cad0ea18b466330325dc6c90","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"1bc64a621160a291c86b8770f3eeaa45a31c31d91c2a071f39981c14fdacb035","benches/bench.rs":"bf8c9a06dad072e14e844daf43895c41d632db183f33fa6de53a43d3677a7375","lib.rs":"dd8993f008a5512d33a74d5e141a4d9d6294baa11174bfeeec2251d731d51957"},"package":"26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"} \ No newline at end of file diff --git a/third_party/rust/smallvec/.travis.yml b/third_party/rust/smallvec/.travis.yml index 7123702a79af..93256e29c5b7 100644 --- a/third_party/rust/smallvec/.travis.yml +++ b/third_party/rust/smallvec/.travis.yml @@ -5,10 +5,9 @@ rust: - stable script: | cargo build --verbose && - cargo build --all-features --verbose && cargo test --verbose && - cargo test --all-features --verbose && - ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --no-default-features) && + ([ $TRAVIS_RUST_VERSION != nightly ] || cargo check --verbose --no-default-features) && + ([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --features union) && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench) notifications: webhooks: http://build.servo.org:54856/travis diff --git a/third_party/rust/smallvec/Cargo.toml b/third_party/rust/smallvec/Cargo.toml index 02191cb84be1..9e7bb4628bfe 100644 --- a/third_party/rust/smallvec/Cargo.toml +++ b/third_party/rust/smallvec/Cargo.toml @@ -12,14 +12,14 @@ [package] name = "smallvec" -version = "0.6.0" +version = "0.6.3" authors = ["Simon Sapin "] description = "'Small vector' optimization: store up to a small number of items on the stack" documentation = "http://doc.servo.org/smallvec/" readme = "README.md" keywords = ["small", "vec", "vector", "stack", "no_std"] categories = ["data-structures"] -license = "MPL-2.0" +license = "MIT/Apache-2.0" repository = "https://github.com/servo/rust-smallvec" [lib] @@ -28,9 +28,13 @@ path = "lib.rs" [dependencies.serde] version = "1" optional = true + +[dependencies.unreachable] +version = "1.0.0" [dev-dependencies.bincode] -version = "0.8" +version = "1.0.1" [features] default = ["std"] std = [] +union = [] diff --git a/third_party/rust/smallvec/LICENSE b/third_party/rust/smallvec/LICENSE deleted file mode 100644 index 398385c9fb9b..000000000000 --- a/third_party/rust/smallvec/LICENSE +++ /dev/null @@ -1,374 +0,0 @@ - Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" -means each individual or legal entity that creates, contributes to -the creation of, or owns Covered Software. - -1.2. "Contributor Version" -means the combination of the Contributions of others (if any) used -by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" -means Covered Software of a particular Contributor. - -1.4. "Covered Software" -means Source Code Form to which the initial Contributor has attached -the notice in Exhibit A, the Executable Form of such Source Code -Form, and Modifications of such Source Code Form, in each case -including portions thereof. - -1.5. "Incompatible With Secondary Licenses" -means - -(a) that the initial Contributor has attached the notice described -in Exhibit B to the Covered Software; or - -(b) that the Covered Software was made available under the terms of -version 1.1 or earlier of the License, but not also under the -terms of a Secondary License. - -1.6. "Executable Form" -means any form of the work other than Source Code Form. - -1.7. "Larger Work" -means a work that combines Covered Software with other material, in -a separate file or files, that is not Covered Software. - -1.8. "License" -means this document. - -1.9. "Licensable" -means having the right to grant, to the maximum extent possible, -whether at the time of the initial grant or subsequently, any and -all of the rights conveyed by this License. - -1.10. "Modifications" -means any of the following: - -(a) any file in Source Code Form that results from an addition to, -deletion from, or modification of the contents of Covered -Software; or - -(b) any new file in Source Code Form that contains any Covered -Software. - -1.11. "Patent Claims" of a Contributor -means any patent claim(s), including without limitation, method, -process, and apparatus claims, in any patent Licensable by such -Contributor that would be infringed, but for the grant of the -License, by the making, using, selling, offering for sale, having -made, import, or transfer of either its Contributions or its -Contributor Version. - -1.12. "Secondary License" -means either the GNU General Public License, Version 2.0, the GNU -Lesser General Public License, Version 2.1, the GNU Affero General -Public License, Version 3.0, or any later versions of those -licenses. - -1.13. "Source Code Form" -means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") -means an individual or a legal entity exercising rights under this -License. For legal entities, "You" includes any entity that -controls, is controlled by, or is under common control with You. For -purposes of this definition, "control" means (a) the power, direct -or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or (b) ownership of more than -fifty percent (50%) of the outstanding shares or beneficial -ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) -Licensable by such Contributor to use, reproduce, make available, -modify, display, perform, distribute, and otherwise exploit its -Contributions, either on an unmodified basis, with Modifications, or -as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer -for sale, have made, import, and otherwise transfer either its -Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; -or - -(b) for infringements caused by: (i) Your and any other third party's -modifications of Covered Software, or (ii) the combination of its -Contributions with other software (except as part of its Contributor -Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of -its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code -Form, as described in Section 3.1, and You must inform recipients of -the Executable Form how they can obtain a copy of such Source Code -Form by reasonable means in a timely manner, at a charge no more -than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this -License, or sublicense it under different terms, provided that the -license for the Executable Form does not attempt to limit or alter -the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - -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/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - -This Source Code Form is "Incompatible With Secondary Licenses", as -defined by the Mozilla Public License, v. 2.0. - diff --git a/third_party/rust/euclid-0.17.3/LICENSE-APACHE b/third_party/rust/smallvec/LICENSE-APACHE similarity index 100% rename from third_party/rust/euclid-0.17.3/LICENSE-APACHE rename to third_party/rust/smallvec/LICENSE-APACHE diff --git a/third_party/rust/euclid-0.17.3/LICENSE-MIT b/third_party/rust/smallvec/LICENSE-MIT similarity index 95% rename from third_party/rust/euclid-0.17.3/LICENSE-MIT rename to third_party/rust/smallvec/LICENSE-MIT index 807526f57f3a..9729c1284e1b 100644 --- a/third_party/rust/euclid-0.17.3/LICENSE-MIT +++ b/third_party/rust/smallvec/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2012-2013 Mozilla Foundation +Copyright (c) 2018 The Servo Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/third_party/rust/smallvec/benches/bench.rs b/third_party/rust/smallvec/benches/bench.rs index 3ca112aab971..c439bec6dabe 100644 --- a/third_party/rust/smallvec/benches/bench.rs +++ b/third_party/rust/smallvec/benches/bench.rs @@ -1,92 +1,248 @@ #![feature(test)] +#[macro_use] extern crate smallvec; extern crate test; -use smallvec::SmallVec; use self::test::Bencher; +use smallvec::{ExtendFromSlice, SmallVec}; -#[bench] -fn bench_push(b: &mut Bencher) { +const VEC_SIZE: usize = 16; +const SPILLED_SIZE: usize = 100; + +trait Vector: for<'a> From<&'a [T]> + Extend + ExtendFromSlice { + fn new() -> Self; + fn push(&mut self, val: T); + fn pop(&mut self) -> Option; + fn remove(&mut self, p: usize) -> T; + fn insert(&mut self, n: usize, val: T); + fn from_elem(val: T, n: usize) -> Self; +} + +impl Vector for Vec { + fn new() -> Self { + Self::with_capacity(VEC_SIZE) + } + + fn push(&mut self, val: T) { + self.push(val) + } + + fn pop(&mut self) -> Option { + self.pop() + } + + fn remove(&mut self, p: usize) -> T { + self.remove(p) + } + + fn insert(&mut self, n: usize, val: T) { + self.insert(n, val) + } + + fn from_elem(val: T, n: usize) -> Self { + vec![val; n] + } +} + +impl Vector for SmallVec<[T; VEC_SIZE]> { + fn new() -> Self { + Self::new() + } + + fn push(&mut self, val: T) { + self.push(val) + } + + fn pop(&mut self) -> Option { + self.pop() + } + + fn remove(&mut self, p: usize) -> T { + self.remove(p) + } + + fn insert(&mut self, n: usize, val: T) { + self.insert(n, val) + } + + fn from_elem(val: T, n: usize) -> Self { + smallvec![val; n] + } +} + +macro_rules! make_benches { + ($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => { + $( + #[bench] + fn $b_name(b: &mut Bencher) { + $g_name::<$typ>($($args,)* b) + } + )* + } +} + +make_benches! { + SmallVec<[u64; VEC_SIZE]> { + bench_push => gen_push(SPILLED_SIZE as _), + bench_push_small => gen_push(VEC_SIZE as _), + bench_insert => gen_insert(SPILLED_SIZE as _), + bench_insert_small => gen_insert(VEC_SIZE as _), + bench_remove => gen_remove(SPILLED_SIZE as _), + bench_remove_small => gen_remove(VEC_SIZE as _), + bench_extend => gen_extend(SPILLED_SIZE as _), + bench_extend_small => gen_extend(VEC_SIZE as _), + bench_from_slice => gen_from_slice(SPILLED_SIZE as _), + bench_from_slice_small => gen_from_slice(VEC_SIZE as _), + bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _), + bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _), + bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _), + bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _), + bench_pushpop => gen_pushpop(), + } +} + +make_benches! { + Vec { + bench_push_vec => gen_push(SPILLED_SIZE as _), + bench_push_vec_small => gen_push(VEC_SIZE as _), + bench_insert_vec => gen_insert(SPILLED_SIZE as _), + bench_insert_vec_small => gen_insert(VEC_SIZE as _), + bench_remove_vec => gen_remove(SPILLED_SIZE as _), + bench_remove_vec_small => gen_remove(VEC_SIZE as _), + bench_extend_vec => gen_extend(SPILLED_SIZE as _), + bench_extend_vec_small => gen_extend(VEC_SIZE as _), + bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _), + bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _), + bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _), + bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _), + bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _), + bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _), + bench_pushpop_vec => gen_pushpop(), + } +} + +fn gen_push>(n: u64, b: &mut Bencher) { #[inline(never)] - fn push_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) { - vec.push(x) + fn push_noinline>(vec: &mut V, x: u64) { + vec.push(x); } b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - for x in 0..100 { + let mut vec = V::new(); + for x in 0..n { push_noinline(&mut vec, x); } vec }); } -#[bench] -fn bench_insert(b: &mut Bencher) { +fn gen_insert>(n: u64, b: &mut Bencher) { #[inline(never)] - fn insert_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) { - vec.insert(0, x) + fn insert_noinline>(vec: &mut V, p: usize, x: u64) { + vec.insert(p, x) } b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - for x in 0..100 { - insert_noinline(&mut vec, x); + let mut vec = V::new(); + // Add one element, with each iteration we insert one before the end. + // This means that we benchmark the insertion operation and not the + // time it takes to `ptr::copy` the data. + vec.push(0); + for x in 0..n { + insert_noinline(&mut vec, x as _, x); } vec }); } +fn gen_remove>(n: usize, b: &mut Bencher) { + #[inline(never)] + fn remove_noinline>(vec: &mut V, p: usize) -> u64 { + vec.remove(p) + } + + b.iter(|| { + let mut vec = V::from_elem(0, n as _); + + for x in (0..n - 1).rev() { + remove_noinline(&mut vec, x); + } + }); +} + +fn gen_extend>(n: u64, b: &mut Bencher) { + b.iter(|| { + let mut vec = V::new(); + vec.extend(0..n); + vec + }); +} + +fn gen_from_slice>(n: u64, b: &mut Bencher) { + let v: Vec = (0..n).collect(); + b.iter(|| { + let vec = V::from(&v); + vec + }); +} + +fn gen_extend_from_slice>(n: u64, b: &mut Bencher) { + let v: Vec = (0..n).collect(); + b.iter(|| { + let mut vec = V::new(); + vec.extend_from_slice(&v); + vec + }); +} + +fn gen_pushpop>(b: &mut Bencher) { + #[inline(never)] + fn pushpop_noinline>(vec: &mut V, x: u64) -> Option { + vec.push(x); + vec.pop() + } + + b.iter(|| { + let mut vec = V::new(); + for x in 0..SPILLED_SIZE as _ { + pushpop_noinline(&mut vec, x); + } + vec + }); +} + +fn gen_from_elem>(n: usize, b: &mut Bencher) { + b.iter(|| { + let vec = V::from_elem(42, n); + vec + }); +} + #[bench] fn bench_insert_many(b: &mut Bencher) { #[inline(never)] - fn insert_many_noinline>( - vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) { + fn insert_many_noinline>( + vec: &mut SmallVec<[u64; VEC_SIZE]>, + index: usize, + iterable: I, + ) { vec.insert_many(index, iterable) } b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - insert_many_noinline(&mut vec, 0, 0..100); - insert_many_noinline(&mut vec, 0, 0..100); - vec - }); -} - -#[bench] -fn bench_extend(b: &mut Bencher) { - b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - vec.extend(0..100); - vec - }); -} - -#[bench] -fn bench_from_slice(b: &mut Bencher) { - let v: Vec = (0..100).collect(); - b.iter(|| { - let vec: SmallVec<[u64; 16]> = SmallVec::from_slice(&v); - vec - }); -} - -#[bench] -fn bench_extend_from_slice(b: &mut Bencher) { - let v: Vec = (0..100).collect(); - b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - vec.extend_from_slice(&v); + let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); + insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); + insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); vec }); } #[bench] fn bench_insert_from_slice(b: &mut Bencher) { - let v: Vec = (0..100).collect(); + let v: Vec = (0..SPILLED_SIZE as _).collect(); b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); + let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); vec.insert_from_slice(0, &v); vec.insert_from_slice(0, &v); vec @@ -94,18 +250,25 @@ fn bench_insert_from_slice(b: &mut Bencher) { } #[bench] -fn bench_pushpop(b: &mut Bencher) { - #[inline(never)] - fn pushpop_noinline(vec: &mut SmallVec<[u64; 16]>, x: u64) { - vec.push(x); - vec.pop(); - } - +fn bench_macro_from_list(b: &mut Bencher) { b.iter(|| { - let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); - for x in 0..100 { - pushpop_noinline(&mut vec, x); - } + let vec: SmallVec<[u64; 16]> = smallvec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, + 0x80000, 0x100000, + ]; + vec + }); +} + +#[bench] +fn bench_macro_from_list_vec(b: &mut Bencher) { + b.iter(|| { + let vec: Vec = vec![ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, + 0x80000, 0x100000, + ]; vec }); } diff --git a/third_party/rust/smallvec/lib.rs b/third_party/rust/smallvec/lib.rs index 09cceab0ecd9..6b302fdee277 100644 --- a/third_party/rust/smallvec/lib.rs +++ b/third_party/rust/smallvec/lib.rs @@ -1,6 +1,8 @@ -/* 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/. */ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. //! Small vectors in various sizes. These store a certain number of elements inline, and fall back //! to the heap for larger allocations. This can be a useful optimization for improving cache @@ -14,22 +16,37 @@ //! //! To depend on `smallvec` without `libstd`, use `default-features = false` in the `smallvec` //! section of Cargo.toml to disable its `"std"` feature. +//! +//! ## `union` feature +//! +//! When the `union` feature is enabled `smallvec` will track its state (inline or spilled) +//! without the use of an enum tag, reducing the size of the `smallvec` by one machine word. +//! This means that there is potentially no space overhead compared to `Vec`. +//! Note that `smallvec` can still be larger than `Vec` if the inline buffer is larger than two +//! machine words. +//! +//! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml. +//! Note that this feature requires a nightly compiler (for now). #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] +#![cfg_attr(feature = "union", feature(untagged_unions))] #![deny(missing_docs)] #[cfg(not(feature = "std"))] -#[cfg_attr(test, macro_use)] +#[macro_use] extern crate alloc; #[cfg(not(feature = "std"))] -use alloc::Vec; +use alloc::vec::Vec; #[cfg(feature = "serde")] extern crate serde; +extern crate unreachable; +use unreachable::UncheckedOptionExt; + #[cfg(not(feature = "std"))] mod std { pub use core::*; @@ -39,8 +56,10 @@ use std::borrow::{Borrow, BorrowMut}; use std::cmp; use std::fmt; use std::hash::{Hash, Hasher}; -use std::iter::{IntoIterator, FromIterator}; +use std::iter::{IntoIterator, FromIterator, repeat}; use std::mem; +#[cfg(not(feature = "union"))] +use std::mem::ManuallyDrop; use std::ops; use std::ptr; use std::slice; @@ -53,7 +72,67 @@ use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; #[cfg(feature = "serde")] use std::marker::PhantomData; -use SmallVecData::{Inline, Heap}; +/// Creates a [`SmallVec`] containing the arguments. +/// +/// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions. +/// There are two forms of this macro: +/// +/// - Create a [`SmallVec`] containing a given list of elements: +/// +/// ``` +/// # #[macro_use] extern crate smallvec; +/// # use smallvec::SmallVec; +/// # fn main() { +/// let v: SmallVec<[_; 128]> = smallvec![1, 2, 3]; +/// assert_eq!(v[0], 1); +/// assert_eq!(v[1], 2); +/// assert_eq!(v[2], 3); +/// # } +/// ``` +/// +/// - Create a [`SmallVec`] from a given element and size: +/// +/// ``` +/// # #[macro_use] extern crate smallvec; +/// # use smallvec::SmallVec; +/// # fn main() { +/// let v: SmallVec<[_; 0x8000]> = smallvec![1; 3]; +/// assert_eq!(v, SmallVec::from_buf([1, 1, 1])); +/// # } +/// ``` +/// +/// Note that unlike array expressions this syntax supports all elements +/// which implement [`Clone`] and the number of elements doesn't have to be +/// a constant. +/// +/// This will use `clone` to duplicate an expression, so one should be careful +/// using this with types having a nonstandard `Clone` implementation. For +/// example, `smallvec![Rc::new(1); 5]` will create a vector of five references +/// to the same boxed integer value, not five references pointing to independently +/// boxed integers. + +#[macro_export] +macro_rules! smallvec { + ($elem:expr; $n:expr) => ({ + SmallVec::from_elem($elem, $n) + }); + ($($x:expr),*$(,)*) => ({ + SmallVec::from_slice(&[$($x),*]) + }); +} + +/// `panic!()` in debug builds, optimization hint in release. +#[cfg(not(feature = "union"))] +macro_rules! debug_unreachable { + () => { debug_unreachable!("entered unreachable code") }; + ($e:expr) => { + if cfg!(not(debug_assertions)) { + unreachable::unreachable(); + } else { + panic!($e); + } + } +} /// Common operations implemented by both `Vec` and `SmallVec`. /// @@ -191,40 +270,90 @@ impl<'a, T: 'a> Drop for Drain<'a,T> { } } -enum SmallVecData { - Inline { array: A }, - Heap { ptr: *mut A::Item, capacity: usize }, +#[cfg(feature = "union")] +#[allow(unions_with_drop_fields)] +union SmallVecData { + inline: A, + heap: (*mut A::Item, usize), } +#[cfg(feature = "union")] impl SmallVecData { - fn ptr_mut(&mut self) -> *mut A::Item { + #[inline] + unsafe fn inline(&self) -> &A { + &self.inline + } + #[inline] + unsafe fn inline_mut(&mut self) -> &mut A { + &mut self.inline + } + #[inline] + fn from_inline(inline: A) -> SmallVecData { + SmallVecData { inline } + } + #[inline] + unsafe fn heap(&self) -> (*mut A::Item, usize) { + self.heap + } + #[inline] + unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) { + &mut self.heap + } + #[inline] + fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + SmallVecData { heap: (ptr, len) } + } +} + +#[cfg(not(feature = "union"))] +enum SmallVecData { + Inline(ManuallyDrop), + Heap((*mut A::Item, usize)), +} + +#[cfg(not(feature = "union"))] +impl SmallVecData { + #[inline] + unsafe fn inline(&self) -> &A { match *self { - Inline { ref mut array } => array.ptr_mut(), - Heap { ptr, .. } => ptr, + SmallVecData::Inline(ref a) => a, + _ => debug_unreachable!(), } } + #[inline] + unsafe fn inline_mut(&mut self) -> &mut A { + match *self { + SmallVecData::Inline(ref mut a) => a, + _ => debug_unreachable!(), + } + } + #[inline] + fn from_inline(inline: A) -> SmallVecData { + SmallVecData::Inline(ManuallyDrop::new(inline)) + } + #[inline] + unsafe fn heap(&self) -> (*mut A::Item, usize) { + match *self { + SmallVecData::Heap(data) => data, + _ => debug_unreachable!(), + } + } + #[inline] + unsafe fn heap_mut(&mut self) -> &mut (*mut A::Item, usize) { + match *self { + SmallVecData::Heap(ref mut data) => data, + _ => debug_unreachable!(), + } + } + #[inline] + fn from_heap(ptr: *mut A::Item, len: usize) -> SmallVecData { + SmallVecData::Heap((ptr, len)) + } } unsafe impl Send for SmallVecData {} unsafe impl Sync for SmallVecData {} -impl Drop for SmallVecData { - fn drop(&mut self) { - unsafe { - match *self { - ref mut inline @ Inline { .. } => { - // Inhibit the array destructor. - ptr::write(inline, Heap { - ptr: ptr::null_mut(), - capacity: 0, - }); - } - Heap { ptr, capacity } => deallocate(ptr, capacity), - } - } - } -} - /// A `Vec`-like container that can store a small number of elements inline. /// /// `SmallVec` acts like a vector, but can store a limited amount of data inline within the @@ -252,7 +381,10 @@ impl Drop for SmallVecData { /// assert!(v.spilled()); /// ``` pub struct SmallVec { - len: usize, + // The capacity field is used to determine which of the storage variants is active: + // If capacity <= A::size() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use). + // If capacity > A::size() then the heap variant is used and capacity holds the size of the memory allocation. + capacity: usize, data: SmallVecData, } @@ -262,8 +394,8 @@ impl SmallVec { pub fn new() -> SmallVec { unsafe { SmallVec { - len: 0, - data: Inline { array: mem::uninitialized() }, + capacity: 0, + data: SmallVecData::from_inline(mem::uninitialized()), } } } @@ -288,8 +420,9 @@ impl SmallVec { v } - /// Construct a new `SmallVec` from a `Vec` without copying - /// elements. + /// Construct a new `SmallVec` from a `Vec`. + /// + /// Elements will be copied to the inline buffer if vec.capacity() <= A::size(). /// /// ```rust /// use smallvec::SmallVec; @@ -301,14 +434,25 @@ impl SmallVec { /// ``` #[inline] pub fn from_vec(mut vec: Vec) -> SmallVec { - let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); - mem::forget(vec); + if vec.capacity() <= A::size() { + unsafe { + let mut data = SmallVecData::::from_inline(mem::uninitialized()); + let len = vec.len(); + vec.set_len(0); + ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().ptr_mut(), len); - SmallVec { - len: len, - data: SmallVecData::Heap { - ptr: ptr, - capacity: cap + SmallVec { + capacity: len, + data, + } + } + } else { + let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); + mem::forget(vec); + + SmallVec { + capacity: cap, + data: SmallVecData::from_heap(ptr, len), } } } @@ -327,8 +471,8 @@ impl SmallVec { #[inline] pub fn from_buf(buf: A) -> SmallVec { SmallVec { - len: A::size(), - data: SmallVecData::Inline { array: buf }, + capacity: A::size(), + data: SmallVecData::from_inline(buf), } } @@ -338,7 +482,8 @@ impl SmallVec { /// modifying its buffers, so it is up to the caller to ensure that the /// vector is actually the specified size. pub unsafe fn set_len(&mut self, new_len: usize) { - self.len = new_len + let (_, len_ptr, _) = self.triple_mut(); + *len_ptr = new_len; } /// The maximum number of elements this vector can hold inline @@ -350,41 +495,62 @@ impl SmallVec { /// The number of elements stored in the vector #[inline] pub fn len(&self) -> usize { - self.len + self.triple().1 } /// Returns `true` if the vector is empty #[inline] pub fn is_empty(&self) -> bool { - self.len == 0 + self.len() == 0 } /// The number of items the vector can hold without reallocating #[inline] pub fn capacity(&self) -> usize { - match self.data { - Inline { .. } => A::size(), - Heap { capacity, .. } => capacity, + self.triple().2 + } + + /// Returns a tuple with (data ptr, len, capacity) + /// Useful to get all SmallVec properties with a single check of the current storage variant. + #[inline] + fn triple(&self) -> (*const A::Item, usize, usize) { + unsafe { + if self.spilled() { + let (ptr, len) = self.data.heap(); + (ptr, len, self.capacity) + } else { + (self.data.inline().ptr(), self.capacity, A::size()) + } + } + } + + /// Returns a tuple with (data ptr, len ptr, capacity) + #[inline] + fn triple_mut(&mut self) -> (*mut A::Item, &mut usize, usize) { + unsafe { + if self.spilled() { + let &mut (ptr, ref mut len_ptr) = self.data.heap_mut(); + (ptr, len_ptr, self.capacity) + } else { + (self.data.inline_mut().ptr_mut(), &mut self.capacity, A::size()) + } } } /// Returns `true` if the data has spilled into a separate heap-allocated buffer. #[inline] pub fn spilled(&self) -> bool { - match self.data { - Inline { .. } => false, - Heap { .. } => true, - } + self.capacity > A::size() } /// Empty the vector and return an iterator over its former contents. pub fn drain(&mut self) -> Drain { unsafe { + let ptr = self.as_mut_ptr(); + let current_len = self.len(); self.set_len(0); - let ptr = self.data.ptr_mut(); - let slice = slice::from_raw_parts_mut(ptr, current_len); Drain { @@ -396,55 +562,57 @@ impl SmallVec { /// Append an item to the vector. #[inline] pub fn push(&mut self, value: A::Item) { - let cap = self.capacity(); - if self.len == cap { - self.grow(cmp::max(cap * 2, 1)) - } unsafe { - let end = self.as_mut_ptr().offset(self.len as isize); - ptr::write(end, value); - let len = self.len; - self.set_len(len + 1) + let (_, &mut len, cap) = self.triple_mut(); + if len == cap { + self.grow(cmp::max(cap * 2, 1)) + } + let (ptr, len_ptr, _) = self.triple_mut(); + *len_ptr = len + 1; + ptr::write(ptr.offset(len as isize), value); } } /// Remove an item from the end of the vector and return it, or None if empty. #[inline] pub fn pop(&mut self) -> Option { - if self.len == 0 { - return None - } - let last_index = self.len - 1; - if (last_index as isize) < 0 { - panic!("overflow") - } unsafe { - let end_ptr = self.as_ptr().offset(last_index as isize); - let value = ptr::read(end_ptr); - self.set_len(last_index); - Some(value) + let (ptr, len_ptr, _) = self.triple_mut(); + if *len_ptr == 0 { + return None; + } + let last_index = *len_ptr - 1; + *len_ptr = last_index; + Some(ptr::read(ptr.offset(last_index as isize))) } } - /// Re-allocate to set the capacity to `new_cap`. + /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. /// /// Panics if `new_cap` is less than the vector's length. pub fn grow(&mut self, new_cap: usize) { - assert!(new_cap >= self.len); - let mut vec: Vec = Vec::with_capacity(new_cap); - let new_alloc = vec.as_mut_ptr(); unsafe { - mem::forget(vec); - ptr::copy_nonoverlapping(self.as_ptr(), new_alloc, self.len); - - match self.data { - Inline { .. } => {} - Heap { ptr, capacity } => deallocate(ptr, capacity), + let (ptr, &mut len, cap) = self.triple_mut(); + let spilled = self.spilled(); + assert!(new_cap >= len); + if new_cap <= self.inline_size() { + if !spilled { + return; + } + self.data = SmallVecData::from_inline(mem::uninitialized()); + ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len); + deallocate(ptr, cap); + } else if new_cap != cap { + let mut vec = Vec::with_capacity(new_cap); + let new_alloc = vec.as_mut_ptr(); + mem::forget(vec); + ptr::copy_nonoverlapping(ptr, new_alloc, len); + self.data = SmallVecData::from_heap(new_alloc, len); + self.capacity = new_cap; + if spilled { + deallocate(ptr, cap); + } } - ptr::write(&mut self.data, Heap { - ptr: new_alloc, - capacity: new_cap, - }); } } @@ -456,12 +624,15 @@ impl SmallVec { /// instead. (This means that inserting `additional` new elements is not guaranteed to be /// possible after calling this function.) pub fn reserve(&mut self, additional: usize) { - let len = self.len(); - if self.capacity() - len < additional { - match len.checked_add(additional).and_then(usize::checked_next_power_of_two) { - Some(cap) => self.grow(cap), - None => self.grow(usize::max_value()), - } + // prefer triple_mut() even if triple() would work + // so that the optimizer removes duplicated calls to it + // from callers like insert() + let (_, &mut len, cap) = self.triple_mut(); + if cap - len < additional { + let new_cap = len.checked_add(additional). + and_then(usize::checked_next_power_of_two). + unwrap_or(usize::max_value()); + self.grow(new_cap); } } @@ -469,8 +640,8 @@ impl SmallVec { /// /// Panics if the new capacity overflows `usize`. pub fn reserve_exact(&mut self, additional: usize) { - let len = self.len(); - if self.capacity() - len < additional { + let (_, &mut len, cap) = self.triple_mut(); + if cap - len < additional { match len.checked_add(additional) { Some(cap) => self.grow(cap), None => panic!("reserve_exact overflow"), @@ -483,16 +654,17 @@ impl SmallVec { /// When possible, this will move data from an external heap buffer to the vector's inline /// storage. pub fn shrink_to_fit(&mut self) { - let len = self.len; + if !self.spilled() { + return; + } + let len = self.len(); if self.inline_size() >= len { unsafe { - let (ptr, capacity) = match self.data { - Inline { .. } => return, - Heap { ptr, capacity } => (ptr, capacity), - }; - ptr::write(&mut self.data, Inline { array: mem::uninitialized() }); - ptr::copy_nonoverlapping(ptr, self.as_mut_ptr(), len); - deallocate(ptr, capacity); + let (ptr, len) = self.data.heap(); + self.data = SmallVecData::from_inline(mem::uninitialized()); + ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len); + deallocate(ptr, self.capacity); + self.capacity = len; } } else if self.capacity() > len { self.grow(len); @@ -507,19 +679,19 @@ impl SmallVec { /// This does not re-allocate. If you want the vector's capacity to shrink, call /// `shrink_to_fit` after truncating. pub fn truncate(&mut self, len: usize) { - let end_ptr = self.as_ptr(); - while len < self.len { - unsafe { - let last_index = self.len - 1; - self.set_len(last_index); - ptr::read(end_ptr.offset(last_index as isize)); + unsafe { + let (ptr, len_ptr, _) = self.triple_mut(); + while len < *len_ptr { + let last_index = *len_ptr - 1; + *len_ptr = last_index; + ptr::drop_in_place(ptr.offset(last_index as isize)); } } } /// Extracts a slice containing the entire vector. /// - /// Equivalent to `&mut s[..]`. + /// Equivalent to `&s[..]`. pub fn as_slice(&self) -> &[A::Item] { self } @@ -538,9 +710,9 @@ impl SmallVec { /// Panics if `index` is out of bounds. #[inline] pub fn swap_remove(&mut self, index: usize) -> A::Item { - let len = self.len; + let len = self.len(); self.swap(len - 1, index); - self.pop().unwrap() + unsafe { self.pop().unchecked_unwrap() } } /// Remove all elements from the vector. @@ -554,15 +726,14 @@ impl SmallVec { /// /// Panics if `index` is out of bounds. pub fn remove(&mut self, index: usize) -> A::Item { - let len = self.len(); - - assert!(index < len); - unsafe { - let ptr = self.as_mut_ptr().offset(index as isize); + let (mut ptr, len_ptr, _) = self.triple_mut(); + let len = *len_ptr; + assert!(index < len); + *len_ptr = len - 1; + ptr = ptr.offset(index as isize); let item = ptr::read(ptr); ptr::copy(ptr.offset(1), ptr, len - index - 1); - self.set_len(len - 1); item } } @@ -573,14 +744,14 @@ impl SmallVec { pub fn insert(&mut self, index: usize, element: A::Item) { self.reserve(1); - let len = self.len; - assert!(index <= len); - unsafe { - let ptr = self.as_mut_ptr().offset(index as isize); + let (mut ptr, len_ptr, _) = self.triple_mut(); + let len = *len_ptr; + assert!(index <= len); + *len_ptr = len + 1; + ptr = ptr.offset(index as isize); ptr::copy(ptr, ptr.offset(1), len - index); ptr::write(ptr, element); - self.set_len(len + 1); } } @@ -588,44 +759,60 @@ impl SmallVec { /// back. pub fn insert_many>(&mut self, index: usize, iterable: I) { let iter = iterable.into_iter(); + if index == self.len() { + return self.extend(iter); + } + let (lower_size_bound, _) = iter.size_hint(); assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable assert!(index + lower_size_bound >= index); // Protect against overflow self.reserve(lower_size_bound); unsafe { - let old_len = self.len; + let old_len = self.len(); assert!(index <= old_len); - let ptr = self.as_mut_ptr().offset(index as isize); + let mut ptr = self.as_mut_ptr().offset(index as isize); + + // Move the trailing elements. ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index); - for (off, element) in iter.enumerate() { - if off < lower_size_bound { - ptr::write(ptr.offset(off as isize), element); - self.len = self.len + 1; - } else { - // Iterator provided more elements than the hint. - assert!(index + off >= index); // Protect against overflow. - self.insert(index + off, element); + + // In case the iterator panics, don't double-drop the items we just copied above. + self.set_len(index); + + let mut num_added = 0; + for element in iter { + let mut cur = ptr.offset(num_added as isize); + if num_added >= lower_size_bound { + // Iterator provided more elements than the hint. Move trailing items again. + self.reserve(1); + ptr = self.as_mut_ptr().offset(index as isize); + cur = ptr.offset(num_added as isize); + ptr::copy(cur, cur.offset(1), old_len - index); } + ptr::write(cur, element); + num_added += 1; } - let num_added = self.len - old_len; if num_added < lower_size_bound { // Iterator provided fewer elements than the hint ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index); } + + self.set_len(old_len + num_added); } } /// Convert a SmallVec to a Vec, without reallocating if the SmallVec has already spilled onto /// the heap. pub fn into_vec(self) -> Vec { - match self.data { - Inline { .. } => self.into_iter().collect(), - Heap { ptr, capacity } => unsafe { - let v = Vec::from_raw_parts(ptr, self.len, capacity); + if self.spilled() { + unsafe { + let (ptr, len) = self.data.heap(); + let v = Vec::from_raw_parts(ptr, len, self.capacity); mem::forget(self); v } + } else { + self.into_iter().collect() } } @@ -636,7 +823,7 @@ impl SmallVec { /// elements. pub fn retain bool>(&mut self, mut f: F) { let mut del = 0; - let len = self.len; + let len = self.len(); for i in 0..len { if !f(&mut self[i]) { del += 1; @@ -653,12 +840,12 @@ impl SmallVec { } /// Removes consecutive duplicate elements using the given equality relation. - pub fn dedup_by(&mut self, mut same_bucket: F) + pub fn dedup_by(&mut self, mut same_bucket: F) where F: FnMut(&mut A::Item, &mut A::Item) -> bool { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. - let len = self.len; + let len = self.len(); if len <= 1 { return; } @@ -684,9 +871,9 @@ impl SmallVec { } /// Removes consecutive elements that map to the same key. - pub fn dedup_by_key(&mut self, mut key: F) - where F: FnMut(&mut A::Item) -> K, - K: PartialEq + pub fn dedup_by_key(&mut self, mut key: F) + where F: FnMut(&mut A::Item) -> K, + K: PartialEq { self.dedup_by(|a, b| key(a) == key(b)); } @@ -709,7 +896,7 @@ impl SmallVec where A::Item: Copy { pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { self.reserve(slice.len()); - let len = self.len; + let len = self.len(); assert!(index <= len); unsafe { @@ -731,16 +918,56 @@ impl SmallVec where A::Item: Copy { } } +impl SmallVec where A::Item: Clone { + /// Resizes the vector so that its length is equal to `len`. + /// + /// If `len` is less than the current length, the vector simply truncated. + /// + /// If `len` is greater than the current length, `value` is appended to the + /// vector until its length equals `len`. + pub fn resize(&mut self, len: usize, value: A::Item) { + let old_len = self.len(); + + if len > old_len { + self.extend(repeat(value).take(len - old_len)); + } else { + self.truncate(len); + } + } + + /// Creates a `SmallVec` with `n` copies of `elem`. + /// ``` + /// use smallvec::SmallVec; + /// + /// let v = SmallVec::<[char; 128]>::from_elem('d', 2); + /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); + /// ``` + pub fn from_elem(elem: A::Item, n: usize) -> Self { + if n > A::size() { + vec![elem; n].into() + } else { + let mut v = SmallVec::::new(); + unsafe { + let (ptr, len_ptr, _) = v.triple_mut(); + let mut local_len = SetLenOnDrop::new(len_ptr); + + for i in 0..n as isize { + ::std::ptr::write(ptr.offset(i), elem.clone()); + local_len.increment_len(1); + } + } + v + } + } +} + impl ops::Deref for SmallVec { type Target = [A::Item]; #[inline] fn deref(&self) -> &[A::Item] { - let ptr: *const _ = match self.data { - Inline { ref array } => array.ptr(), - Heap { ptr, .. } => ptr, - }; unsafe { - slice::from_raw_parts(ptr, self.len) + let (ptr, len, _) = self.triple(); + slice::from_raw_parts(ptr, len) } } } @@ -748,9 +975,9 @@ impl ops::Deref for SmallVec { impl ops::DerefMut for SmallVec { #[inline] fn deref_mut(&mut self) -> &mut [A::Item] { - let ptr = self.data.ptr_mut(); unsafe { - slice::from_raw_parts_mut(ptr, self.len) + let (ptr, &mut len, _) = self.triple_mut(); + slice::from_raw_parts_mut(ptr, len) } } } @@ -921,13 +1148,23 @@ impl FromIterator for SmallVec { impl Extend for SmallVec { fn extend>(&mut self, iterable: I) { - let iter = iterable.into_iter(); + let mut iter = iterable.into_iter(); let (lower_size_bound, _) = iter.size_hint(); + self.reserve(lower_size_bound); - let target_len = self.len + lower_size_bound; - - if target_len > self.capacity() { - self.grow(target_len); + unsafe { + let len = self.len(); + let ptr = self.as_mut_ptr().offset(len as isize); + let mut count = 0; + while count < lower_size_bound { + if let Some(out) = iter.next() { + ptr::write(ptr.offset(count as isize), out); + count += 1; + } else { + break; + } + } + self.set_len(len + count); } for elem in iter { @@ -951,12 +1188,12 @@ impl Default for SmallVec { impl Drop for SmallVec { fn drop(&mut self) { - // Note on panic safety: dropping an element may panic, - // but the inner SmallVecData destructor will still run unsafe { - let ptr = self.as_ptr(); - for i in 0 .. self.len { - ptr::read(ptr.offset(i as isize)); + if self.spilled() { + let (ptr, len) = self.data.heap(); + Vec::from_raw_parts(ptr, len, self.capacity); + } else { + ptr::drop_in_place(&mut self[..]); } } } @@ -1010,7 +1247,7 @@ unsafe impl Send for SmallVec where A::Item: Send {} /// /// [1]: struct.SmallVec.html#method.into_iter pub struct IntoIter { - data: SmallVecData, + data: SmallVec, current: usize, end: usize, } @@ -1033,7 +1270,7 @@ impl Iterator for IntoIter { unsafe { let current = self.current as isize; self.current += 1; - Some(ptr::read(self.data.ptr_mut().offset(current))) + Some(ptr::read(self.data.as_ptr().offset(current))) } } } @@ -1054,7 +1291,7 @@ impl DoubleEndedIterator for IntoIter { else { unsafe { self.end -= 1; - Some(ptr::read(self.data.ptr_mut().offset(self.end as isize))) + Some(ptr::read(self.data.as_ptr().offset(self.end as isize))) } } } @@ -1066,13 +1303,12 @@ impl IntoIterator for SmallVec { type IntoIter = IntoIter; type Item = A::Item; fn into_iter(mut self) -> Self::IntoIter { - let len = self.len(); unsafe { - // Only grab the `data` field, the `IntoIter` type handles dropping of the elements - let data = ptr::read(&mut self.data); - mem::forget(self); + // Set SmallVec len to zero as `IntoIter` drop handles dropping of the elements + let len = self.len(); + self.set_len(0); IntoIter { - data: data, + data: self, current: 0, end: len, } @@ -1108,20 +1344,47 @@ pub unsafe trait Array { fn ptr_mut(&mut self) -> *mut Self::Item; } +/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +/// +/// Copied from https://github.com/rust-lang/rust/pull/36355 +struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len: len } + } + + #[inline] + fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } +} + +impl<'a> Drop for SetLenOnDrop<'a> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} + macro_rules! impl_array( ($($size:expr),+) => { $( unsafe impl Array for [T; $size] { type Item = T; fn size() -> usize { $size } - fn ptr(&self) -> *const T { &self[0] } - fn ptr_mut(&mut self) -> *mut T { &mut self[0] } + fn ptr(&self) -> *const T { self.as_ptr() } + fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() } } )+ } ); -impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, +impl_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000); @@ -1144,6 +1407,15 @@ mod tests { #[cfg(not(feature = "std"))] use alloc::vec::Vec; + #[test] + pub fn test_zero() { + let mut v = SmallVec::<[_; 0]>::new(); + assert!(!v.spilled()); + v.push(0usize); + assert!(v.spilled()); + assert_eq!(&*v, &[0]); + } + // We heap allocate all these strings so that double frees will show up under valgrind. #[test] @@ -1407,6 +1679,37 @@ mod tests { assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); } + #[test] + // https://github.com/servo/rust-smallvec/issues/96 + fn test_insert_many_panic() { + struct PanicOnDoubleDrop { + dropped: Box + } + + impl Drop for PanicOnDoubleDrop { + fn drop(&mut self) { + assert!(!*self.dropped, "already dropped"); + *self.dropped = true; + } + } + + struct BadIter; + impl Iterator for BadIter { + type Item = PanicOnDoubleDrop; + fn size_hint(&self) -> (usize, Option) { (1, None) } + fn next(&mut self) -> Option { panic!() } + } + + let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = vec![ + PanicOnDoubleDrop { dropped: Box::new(false) }, + PanicOnDoubleDrop { dropped: Box::new(false) }, + ].into(); + let result = ::std::panic::catch_unwind(move || { + vec.insert_many(0, BadIter); + }); + assert!(result.is_err()); + } + #[test] #[should_panic] fn test_invalid_grow() { @@ -1733,6 +2036,17 @@ mod tests { assert_eq!(no_dupes.len(), 5); } + #[test] + fn test_resize() { + let mut v: SmallVec<[i32; 8]> = SmallVec::new(); + v.push(1); + v.resize(5, 0); + assert_eq!(v[..], [1, 0, 0, 0, 0][..]); + + v.resize(2, -1); + assert_eq!(v[..], [1, 0][..]); + } + #[cfg(feature = "std")] #[test] fn test_write() {