Merge branch 'release/1.0.0'
This commit is contained in:
commit
bc571b10a8
24 changed files with 921 additions and 164 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,9 +1,7 @@
|
|||
*.png
|
||||
*.json
|
||||
*.svg
|
||||
!pool/**/*.svg
|
||||
!pool/**/*.png
|
||||
!pool/**/*.json
|
||||
!images/**/*.png
|
||||
|
||||
.idea
|
||||
|
||||
|
|
192
Cargo.lock
generated
192
Cargo.lock
generated
|
@ -29,6 +29,11 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.3.2"
|
||||
|
@ -119,25 +124,26 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
version = "0.8.1"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-sys-rs"
|
||||
version = "0.9.2"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -454,7 +460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.9.3"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -463,19 +469,35 @@ dependencies = [
|
|||
"futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-macros 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"once_cell 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-macros"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"anyhow 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.9.1"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -485,12 +507,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.9.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glib-sys 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -552,6 +574,14 @@ dependencies = [
|
|||
"either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -629,6 +659,11 @@ name = "object"
|
|||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "palette"
|
||||
version = "0.5.0"
|
||||
|
@ -709,7 +744,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "polygon-art"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"cairo-rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cairo-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"geo 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"geo-clipper 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"geo-svg-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -726,6 +761,14 @@ name = "ppv-lite86"
|
|||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"toml 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "0.4.9"
|
||||
|
@ -738,6 +781,18 @@ dependencies = [
|
|||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "0.4.9"
|
||||
|
@ -750,6 +805,16 @@ dependencies = [
|
|||
"syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version_check 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.11"
|
||||
|
@ -939,6 +1004,11 @@ dependencies = [
|
|||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "0.1.1"
|
||||
|
@ -996,6 +1066,22 @@ dependencies = [
|
|||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "svg"
|
||||
version = "0.9.1"
|
||||
|
@ -1041,6 +1127,20 @@ dependencies = [
|
|||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"version-compare 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
|
@ -1057,6 +1157,24 @@ dependencies = [
|
|||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thiserror-impl 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpool"
|
||||
version = "1.8.1"
|
||||
|
@ -1065,6 +1183,14 @@ dependencies = [
|
|||
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde 1.0.125 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.13.0"
|
||||
|
@ -1090,6 +1216,11 @@ name = "vec_map"
|
|||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
@ -1150,6 +1281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum adler 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
"checksum aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum anyhow 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||
"checksum as-slice 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
|
||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
|
@ -1159,8 +1291,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||
"checksum cairo-rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "157049ba9618aa3a61c39d5d785102c04d3b1f40632a706c621a9aedc21e6084"
|
||||
"checksum cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63"
|
||||
"checksum cairo-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c5c0f2e047e8ca53d0ff249c54ae047931d7a6ebe05d00af73e0ffeb6e34bdb8"
|
||||
"checksum cairo-sys-rs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7"
|
||||
"checksum cc 1.0.67 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
"checksum cexpr 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
@ -1196,10 +1328,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
"checksum getrandom 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
"checksum gimli 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
||||
"checksum glib 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "40fb573a09841b6386ddf15fd4bc6655b4f5b106ca962f57ecaecde32a0061c0"
|
||||
"checksum glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2"
|
||||
"checksum glib 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0c685013b7515e668f1b57a165b009d4d28cb139a8a989bbd699c10dad29d0c5"
|
||||
"checksum glib-macros 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039"
|
||||
"checksum glib-sys 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1"
|
||||
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
"checksum gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9"
|
||||
"checksum gobject-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c"
|
||||
"checksum hash32 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
|
||||
"checksum heapless 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
|
@ -1207,6 +1340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||
"checksum iso8601 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cee08a007a59a8adfc96f69738ddf59e374888dfd84b49c4b916543067644d58"
|
||||
"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
|
||||
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum lazycell 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
|
||||
|
@ -1218,6 +1352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
"checksum object 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
|
||||
"checksum once_cell 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
"checksum palette 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a05c0334468e62a4dfbda34b29110aa7d70d58c7fdb2c9857b5874dd9827cc59"
|
||||
"checksum palette_derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b4b5f600e60dd3a147fb57b4547033d382d1979eb087af310e91cb45a63b1f4"
|
||||
"checksum pdqselect 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27"
|
||||
|
@ -1229,8 +1364,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum ppv-lite86 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
"checksum proc-macro-crate 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
|
||||
"checksum proc-macro-error 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "052b3c9af39c7e5e94245f820530487d19eb285faedcb40e0c3275132293f242"
|
||||
"checksum proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
"checksum proc-macro-error-attr 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d175bef481c7902e63e3165627123fff3502f06ac043d3ef42d08c1246da9253"
|
||||
"checksum proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
|
||||
"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
|
||||
"checksum proc-macro2 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
|
@ -1255,6 +1393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rustc-demangle 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
|
||||
"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
"checksum rustversion 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
|
||||
"checksum serde 1.0.125 (registry+https://github.com/rust-lang/crates.io-index)" = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||
"checksum siphasher 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27"
|
||||
|
@ -1264,19 +1403,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum structopt 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98"
|
||||
"checksum structopt-derive 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64"
|
||||
"checksum strum 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
|
||||
"checksum strum_macros 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
|
||||
"checksum svg 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a95656b5b37251de210aa2751d538b6f31ce375bacf725a32223bfa6344e0776"
|
||||
"checksum svgtypes 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff"
|
||||
"checksum syn 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)" = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
|
||||
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
"checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
"checksum system-deps 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
|
||||
"checksum termcolor 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thiserror 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
|
||||
"checksum thiserror-impl 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||
"checksum threadpool 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
||||
"checksum toml 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
"checksum typenum 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum version-compare 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
|
||||
"checksum version_check 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
"checksum wasi 0.10.2+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
|
|
@ -4,8 +4,9 @@ version = "1.0.0"
|
|||
authors = ["Ingolf Wagner <contact@ingolf-wagner.de>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
description = "Convenience library to use geo polygons to create art."
|
||||
description = "Convenience library to use geo to create art."
|
||||
documentation = "https://github.com/mrVanDalo/polygon-art"
|
||||
homepage = "https://github.com/mrVanDalo/polygon-art"
|
||||
repository = "https://github.com/mrVanDalo/polygon-art"
|
||||
|
@ -17,7 +18,7 @@ maintenance = { status = "actively-developed" }
|
|||
exclude = [ "shell.nix", "default.nix" ]
|
||||
|
||||
[dependencies]
|
||||
cairo-rs = { version = "0.8", features = [ "png", "svg"] }
|
||||
cairo-rs = { version = "0.9", features = [ "png", "svg" ] }
|
||||
geo = "0.16"
|
||||
geo-clipper = "0.4.0"
|
||||
geo-svg-io = "0.1.1"
|
||||
|
|
16
README.md
16
README.md
|
@ -1,12 +1,22 @@
|
|||
Convenience library to create art using [geo](https://georust.org/)
|
||||
polygons.
|
||||
Convenience library to create art using [geo](https://georust.org/).
|
||||
|
||||
* Creates CLI interface (including random seed management)
|
||||
* renders SVGs and PNG
|
||||
* comes with helper functions, to make live more convenient.
|
||||
* comes with helper functions and extensions, to make live more convenient.
|
||||
* load SVGs
|
||||
* scaling
|
||||
|
||||
# Asteroids
|
||||
|
||||
asteroids is an example binary which renders an
|
||||
image inspired by the
|
||||
[asteroids game from the 1979](https://de.wikipedia.org/wiki/Asteroids).
|
||||
|
||||
![image](./images/asteroids.png)
|
||||
|
||||
run `asteroids --help` to get information.
|
||||
All binaries created by polygon art have the same
|
||||
command line interface.
|
||||
|
||||
# How to run examples
|
||||
|
||||
|
|
27
default.nix
27
default.nix
|
@ -1,27 +0,0 @@
|
|||
{ rustPlatform, fetchgit, stdenv, cairo, ... }:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
name = "image-geneartor-${version}";
|
||||
version = "3.0.0";
|
||||
# src = ./.;
|
||||
src = fetchgit{
|
||||
url = "https://github.com/mrVanDalo/image-generator";
|
||||
rev = "f8c1bf958aeea1808df6baea62eeb2949aa5fe65";
|
||||
sha256 = "1swa2i57sdag3zapzx3m9mdarci0xfjczr611320zampw505ai09";
|
||||
};
|
||||
|
||||
cargoSha256 = "07pwds279qc54g5fza805ah2m8jhrdzng7vb1bi24a9ra9ci8s29";
|
||||
verifyCargoDeps = true;
|
||||
|
||||
buildInputs = [ cairo ];
|
||||
|
||||
meta = with stdenv.lib; {
|
||||
description =
|
||||
"An image generator unsing entropy and a JSON as configuration.";
|
||||
homepage = "https://github.com/mrVanDalo/image-generator";
|
||||
license = licenses.gplv3;
|
||||
maintainers = [ maintainers.mrVanDalo ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ fn main() {
|
|||
context.draw_multipolygon(union);
|
||||
|
||||
// intersection
|
||||
context.save();
|
||||
context.translate(0.0, 250.);
|
||||
let intersection = &polygon_a.intersection(&polygon_b, 10.0);
|
||||
context.draw_multipolygon(intersection);
|
||||
|
@ -51,7 +52,6 @@ fn main() {
|
|||
context.translate(0., 250.);
|
||||
let difference = &polygon_b.difference(&polygon_a, 10.0);
|
||||
context.draw_multipolygon(difference);
|
||||
context.restore();
|
||||
|
||||
context.render();
|
||||
}
|
||||
|
|
35
examples/font.rs
Normal file
35
examples/font.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
//! Shows how to use buildin font
|
||||
|
||||
use geo::line_string;
|
||||
use polygon_art::{AsteroidFont, Context, FontDirection};
|
||||
use FontDirection::{LeftRight, TopDown};
|
||||
|
||||
fn main() {
|
||||
let context = Context::create();
|
||||
context.save();
|
||||
context.translate(70., 50.);
|
||||
|
||||
let font = AsteroidFont::new();
|
||||
let line = font.get_text("Hey there!".to_string(), 12., LeftRight);
|
||||
context.draw_multiline_string(&line);
|
||||
context.draw_line_string(&line_string![(x : 0., y:14.), (x: 1000. , y : 14.)]);
|
||||
|
||||
context.translate(0.0, 18.);
|
||||
let line = font.get_text("How are you?".to_string(), 22., LeftRight);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.translate(0.0, 28.);
|
||||
let line = font.get_text("Here a bitter text!".to_string(), 50., LeftRight);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.translate(0.0, 56.);
|
||||
let line = font.get_text("0123456789".to_string(), 50., LeftRight);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.restore();
|
||||
context.translate(30., 50.);
|
||||
let line = font.get_text("0123456789".to_string(), 30., TopDown);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.render();
|
||||
}
|
|
@ -3,16 +3,16 @@
|
|||
use geo::rotate::RotatePoint;
|
||||
use geo::translate::Translate;
|
||||
use geo::{Coordinate, Point};
|
||||
use polygon_art::load_multipolgon_from_svg;
|
||||
use polygon_art::Context;
|
||||
use polygon_art::MultiPolygonExt;
|
||||
use polygon_art::TranslateExt;
|
||||
use polygon_art::{load_multipolygon_from_svg, ScaleExt};
|
||||
use rand::Rng;
|
||||
|
||||
fn main() {
|
||||
let mut renderer = Context::create();
|
||||
|
||||
let path = "pool/examples/example.svg";
|
||||
let svg = load_multipolgon_from_svg(path).expect("couldn't load svg");
|
||||
let svg = load_multipolygon_from_svg(path).expect("couldn't load svg");
|
||||
|
||||
let item_space = 110.;
|
||||
|
||||
|
@ -43,6 +43,5 @@ fn main() {
|
|||
renderer.draw_multipolygon(&svg);
|
||||
}
|
||||
|
||||
renderer.restore();
|
||||
renderer.render();
|
||||
}
|
||||
|
|
BIN
images/asteroids.png
Normal file
BIN
images/asteroids.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
34
pool/asteroids/ship1.svg
Normal file
34
pool/asteroids/ship1.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path845"
|
||||
d="M 5.9999998,0 2,12 5.9999998,11 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 940 B |
34
pool/asteroids/ship2.svg
Normal file
34
pool/asteroids/ship2.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path869"
|
||||
d="M 5.9999998,0 2,12 3.9058027,11 H 7.9098644 L 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 954 B |
34
pool/asteroids/ship3.svg
Normal file
34
pool/asteroids/ship3.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path869"
|
||||
d="M 5.9999998,0 2,12 3.9058027,9.4125 H 7.9098644 L 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 958 B |
|
@ -12,6 +12,7 @@ pkgs.mkShell {
|
|||
|
||||
clang
|
||||
llvm
|
||||
pkg-config
|
||||
|
||||
(pkgs.writers.writeBashBin "reformat" ''
|
||||
for file in `find ${toString ./.} -type f | egrep "\.rs$"`
|
||||
|
@ -24,7 +25,8 @@ pkgs.mkShell {
|
|||
# run this on start
|
||||
# -----------------
|
||||
shellHook = ''
|
||||
export NIX_ENFORCE_PURITY=0
|
||||
# export NIX_ENFORCE_PURITY=0
|
||||
|
||||
# Needed so bindgen can find libclang.so
|
||||
export LIBCLANG_PATH="${pkgs.llvmPackages.libclang}/lib";
|
||||
'';
|
||||
|
|
150
src/bin/asteroids.rs
Normal file
150
src/bin/asteroids.rs
Normal file
|
@ -0,0 +1,150 @@
|
|||
use geo::algorithm::intersects::Intersects;
|
||||
use geo::algorithm::rotate::Rotate;
|
||||
use geo::prelude::Translate;
|
||||
use geo::rotate::RotatePoint;
|
||||
use geo::LineString;
|
||||
use geo::{polygon, Coordinate, MultiPolygon, Point, Polygon};
|
||||
use geo_clipper::Clipper;
|
||||
use polygon_art::{load_multipolygon_from_svg_include, Context, MergeExt, ScaleExt};
|
||||
use polygon_art::{AsteroidFont, FontDirection, TranslateExt};
|
||||
use rand::prelude::StdRng;
|
||||
use rand::Rng;
|
||||
|
||||
/// A more or less complete example that illustrates various technics
|
||||
fn main() {
|
||||
let mut context = Context::create();
|
||||
let mut rng = context.gen_rng();
|
||||
|
||||
let width = context.width;
|
||||
let height = context.height;
|
||||
let diagonal = f64::sqrt(width * width + height * height);
|
||||
|
||||
let frame_offset = diagonal * 0.01;
|
||||
let max_asteroid = (diagonal / 80.) as usize;
|
||||
|
||||
let min_asteroid_size = diagonal / 50.;
|
||||
let max_asteroid_size = diagonal / 12.;
|
||||
let ship_length = diagonal / 23.;
|
||||
let ship_orbit = 3.0;
|
||||
|
||||
let center_point = MultiPolygon(vec![create_asteroid(&mut rng, 8, 2)])
|
||||
.scale_to_width(ship_orbit * ship_length)
|
||||
.translate(width / 2., height / 2.);
|
||||
|
||||
// create asteroid
|
||||
let mut asteroids: MultiPolygon<f64> = MultiPolygon(Vec::new());
|
||||
for _ in 0..(max_asteroid * 2) {
|
||||
let without_orbit = rng.gen_range(min_asteroid_size..max_asteroid_size) as f64;
|
||||
let with_orbit = without_orbit * 1.32;
|
||||
let x = rng.gen_range(0..(context.width as i32)) as f64;
|
||||
let y = rng.gen_range(0..(context.height as i32)) as f64;
|
||||
let asteroid = MultiPolygon(vec![create_asteroid(&mut rng, 20, 15)])
|
||||
.scale_to_width(with_orbit)
|
||||
.translate(x, y);
|
||||
|
||||
if (!center_point.intersects(&asteroid)) && !asteroids.intersects(&asteroid) {
|
||||
// asteroids.push(asteroid.scale_to_width(without_orbit));
|
||||
asteroids.merge_destructive(&mut asteroid.scale_to_width(without_orbit))
|
||||
}
|
||||
if asteroids.0.len() > max_asteroid {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// load ships
|
||||
let rotation = rng.gen_range(0..360);
|
||||
let ship_yard = [
|
||||
include_str!("../../pool/asteroids/ship1.svg"),
|
||||
include_str!("../../pool/asteroids/ship2.svg"),
|
||||
include_str!("../../pool/asteroids/ship3.svg"),
|
||||
];
|
||||
let chosen_ship = rng.gen_range(0..3);
|
||||
let raw_ship = load_multipolygon_from_svg_include(ship_yard[chosen_ship])
|
||||
.unwrap()
|
||||
// rotate to scale ship with width
|
||||
.rotate(90.);
|
||||
let ship = raw_ship
|
||||
.scale_to_width(ship_length)
|
||||
.translate_center()
|
||||
.rotate(rotation as f64);
|
||||
context.save();
|
||||
context.translate_center();
|
||||
context.draw_multipolygon(&ship);
|
||||
context.restore();
|
||||
|
||||
// draw score board
|
||||
let font = AsteroidFont::new();
|
||||
let random_seed_string = context.seed.to_string();
|
||||
let font_size = 20.;
|
||||
let (x_font_size, y_font_size) = font.get_text_scale_factor(font_size);
|
||||
let score_board_letters = random_seed_string.len();
|
||||
let window = context.frame(frame_offset, frame_offset, frame_offset, frame_offset);
|
||||
let window_height = frame_offset + y_font_size;
|
||||
let window_width = frame_offset + score_board_letters as f64 * x_font_size;
|
||||
let score_board: Polygon<f64> = polygon![(x:0., y:0.), (x: window_width, y:0.), (x: window_width, y: window_height), (x: 0., y: window_height)];
|
||||
let score_board_lines = font.get_text(random_seed_string, font_size, FontDirection::LeftRight);
|
||||
context.save();
|
||||
context.translate(frame_offset, frame_offset);
|
||||
context.draw_multiline_string(&score_board_lines);
|
||||
context.restore();
|
||||
|
||||
// draw life board
|
||||
let life = rng.gen_range(2..7) as f64;
|
||||
let life_board: Polygon<f64> = polygon![
|
||||
(x:width, y:0.),
|
||||
(x: width - frame_offset - life * x_font_size - 3., y:0.),
|
||||
(x: width - frame_offset - life * x_font_size - 3., y:frame_offset + y_font_size + 3.),
|
||||
(x: width , y:frame_offset + y_font_size + 3.)
|
||||
];
|
||||
|
||||
let life_ship = raw_ship
|
||||
.scale_to_width(font_size)
|
||||
.rotate(-90.)
|
||||
.translate_center_y()
|
||||
.translate_top();
|
||||
for l in 1..(1 + life as i32) {
|
||||
context.save();
|
||||
context.translate(
|
||||
width - frame_offset - (x_font_size * l as f64) as f64,
|
||||
frame_offset,
|
||||
);
|
||||
context.draw_multipolygon(&life_ship);
|
||||
context.restore();
|
||||
}
|
||||
|
||||
// draw window
|
||||
let window = window.difference(&score_board, 100.);
|
||||
let window = window.difference(&life_board, 100.);
|
||||
context.draw_multipolygon(&window);
|
||||
|
||||
// draw asteroids
|
||||
context.draw_multipolygon(&asteroids.intersection(&window, 100.));
|
||||
|
||||
// render image
|
||||
context.render();
|
||||
}
|
||||
|
||||
fn create_asteroid(rng: &mut StdRng, subdivisions: i32, radius_randomization: i32) -> Polygon<f64> {
|
||||
let mut asteroid_points: Vec<Point<f64>> = Vec::new();
|
||||
for _ in 0..subdivisions {
|
||||
let change = rng.gen_range(0..(radius_randomization * 2));
|
||||
asteroid_points.push(Point(Coordinate {
|
||||
x: 0.0,
|
||||
y: 100.0 + (change - radius_randomization) as f64,
|
||||
}));
|
||||
for point in asteroid_points.iter_mut() {
|
||||
let (x, y) = point
|
||||
.rotate_around_point(
|
||||
360. / subdivisions as f64,
|
||||
Point(Coordinate { x: 0., y: 0. }),
|
||||
)
|
||||
.x_y();
|
||||
point.set_x(x);
|
||||
point.set_y(y);
|
||||
}
|
||||
}
|
||||
Polygon::new(
|
||||
LineString(asteroid_points.iter().map(|point| point.0).collect()),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use cairo::Format;
|
||||
use cairo::{ImageSurface, SvgSurface};
|
||||
use geo_types::{LineString, MultiPolygon, Polygon};
|
||||
use geo::{polygon, LineString, MultiLineString, MultiPolygon, Polygon};
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
|
@ -19,9 +19,25 @@ pub struct Context {
|
|||
pub width: f64,
|
||||
pub line_size: f64,
|
||||
pub pseudo_random_number_generator: Box<StdRng>,
|
||||
pub seed: u64,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// generate a frame for the image
|
||||
pub fn frame(&mut self, left: f64, bottom: f64, right: f64, top: f64) -> Polygon<f64> {
|
||||
polygon![
|
||||
(x: left, y: top),
|
||||
(x: self.width - right, y: top),
|
||||
(x: self.width - right, y: self.height - bottom),
|
||||
(x: left , y: self.height - bottom),
|
||||
]
|
||||
}
|
||||
|
||||
/// a fall back operation, if you need a function not provided by this struct.
|
||||
pub fn cairo_context(&self) -> &cairo::Context {
|
||||
self.render_container.context()
|
||||
}
|
||||
|
||||
pub fn draw_multipolygon(&self, multi_polygon: &MultiPolygon<f64>) {
|
||||
for polygon in multi_polygon.iter() {
|
||||
self.draw_polygon(polygon);
|
||||
|
@ -29,13 +45,13 @@ impl Context {
|
|||
}
|
||||
|
||||
pub fn draw_polygon(&self, polygon: &Polygon<f64>) {
|
||||
self.plot_line_string(polygon.exterior());
|
||||
self.draw_line_string(polygon.exterior());
|
||||
for interior in polygon.interiors() {
|
||||
self.plot_line_string(interior);
|
||||
self.draw_line_string(interior);
|
||||
}
|
||||
}
|
||||
|
||||
fn plot_line_string(&self, line_string: &LineString<f64>) {
|
||||
pub fn draw_line_string(&self, line_string: &LineString<f64>) {
|
||||
let context = self.render_container.context();
|
||||
let mut init = true;
|
||||
for point in line_string.clone().into_points() {
|
||||
|
@ -48,19 +64,31 @@ impl Context {
|
|||
}
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
pub fn draw_line_strings(&self, line_strings: &Vec<LineString<f64>>) {
|
||||
for lines in line_strings {
|
||||
self.draw_line_string(&lines);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_multiline_string(&self, multilinestring: &MultiLineString<f64>) {
|
||||
for line in multilinestring.iter() {
|
||||
self.draw_line_string(line);
|
||||
}
|
||||
}
|
||||
|
||||
// cairo facades
|
||||
impl Context {
|
||||
/// restore state which was saved before by the context
|
||||
pub fn restore(&self) {
|
||||
self.render_container.context().restore();
|
||||
}
|
||||
|
||||
/// save state to restore later again
|
||||
pub fn save(&self) {
|
||||
self.render_container.context().save();
|
||||
}
|
||||
/// scale, but line with stays
|
||||
pub fn scale(&self, factor: f64) {
|
||||
let context = self.render_container.context();
|
||||
context.save();
|
||||
context.scale(factor, factor);
|
||||
context.set_line_width(1. / factor);
|
||||
}
|
||||
|
@ -73,7 +101,6 @@ impl Context {
|
|||
/// translate to a position
|
||||
pub fn translate(&self, tx: f64, ty: f64) {
|
||||
let context = self.render_container.context();
|
||||
context.save();
|
||||
context.translate(tx, ty);
|
||||
}
|
||||
|
||||
|
@ -81,12 +108,32 @@ impl Context {
|
|||
self.render_container.render();
|
||||
}
|
||||
|
||||
pub fn gen_rng(&mut self) -> StdRng {
|
||||
StdRng::seed_from_u64(self.pseudo_random_number_generator.gen())
|
||||
}
|
||||
|
||||
pub fn create() -> Context {
|
||||
let opt = Opt::get_command_line_arguments();
|
||||
let height = f64::from(opt.height.clone());
|
||||
let width = f64::from(opt.width.clone());
|
||||
let line_size = opt.line_size.clone();
|
||||
|
||||
let mm = 3.779527547619048; // calculated with inkscape 1587.40157 (px) / 420 (mm) (from a3)
|
||||
let (mut height, mut width) = match opt.format {
|
||||
None => (f64::from(opt.height.clone()), f64::from(opt.width.clone())),
|
||||
Some(format) => match &format[..] {
|
||||
"a3" => (297. * mm, 420. * mm),
|
||||
"a4" => (210. * mm, 297. * mm),
|
||||
"a5" => (148. * mm, 210. * mm),
|
||||
"x220" => (768., 1366.),
|
||||
_ => (f64::from(opt.height.clone()), f64::from(opt.width.clone())),
|
||||
},
|
||||
};
|
||||
|
||||
if opt.orientation == "portrait" {
|
||||
let cache = height;
|
||||
height = width;
|
||||
width = cache;
|
||||
}
|
||||
|
||||
let random_seed = match opt.random_seed {
|
||||
Some(random_seed) => random_seed,
|
||||
None => match opt.random_seed_date {
|
||||
|
@ -118,8 +165,7 @@ impl Context {
|
|||
.expect("Can't svg surface");
|
||||
Box::new(SvgRenderContainer::new(svg_surface, palette)) as Box<dyn RenderContainer>
|
||||
} else if opt.output_type == "png" {
|
||||
let png_surface =
|
||||
ImageSurface::create(Format::Rgb24, opt.width.clone(), opt.height.clone())
|
||||
let png_surface = ImageSurface::create(Format::Rgb24, width as i32, height as i32)
|
||||
.expect("Can't create png surface");
|
||||
Box::new(PngRenderContainer::new(
|
||||
opt.output.to_string_lossy().to_string(),
|
||||
|
@ -138,6 +184,7 @@ impl Context {
|
|||
line_size,
|
||||
pseudo_random_number_generator: Box::new(rng),
|
||||
render_container,
|
||||
seed: random_seed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,13 +13,30 @@ pub struct Opt {
|
|||
pub output: PathBuf,
|
||||
|
||||
/// define width in pixels
|
||||
#[structopt(long, default_value = "400")]
|
||||
#[structopt(long, default_value = "600")]
|
||||
pub width: i32,
|
||||
|
||||
/// define height in pixels
|
||||
#[structopt(long, default_value = "400")]
|
||||
pub height: i32,
|
||||
|
||||
/// use a predefined format
|
||||
#[structopt(
|
||||
long,
|
||||
conflicts_with="height",
|
||||
conflicts_with="width",
|
||||
possible_values=&["a3", "a4", "a5", "x220"]
|
||||
)]
|
||||
pub format: Option<String>,
|
||||
|
||||
/// change orientation
|
||||
#[structopt(
|
||||
long,
|
||||
default_value="landscape",
|
||||
possible_values=&["portrait", "landscape"]
|
||||
)]
|
||||
pub orientation: String,
|
||||
|
||||
/// define line size in pixels, all lines will be this thick
|
||||
#[structopt(long, default_value = "1.0")]
|
||||
pub line_size: f64,
|
||||
|
|
3
src/extensions.rs
Normal file
3
src/extensions.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub(crate) mod merge_ext;
|
||||
pub(crate) mod scale_ext;
|
||||
pub(crate) mod translate_ext;
|
35
src/extensions/merge_ext.rs
Normal file
35
src/extensions/merge_ext.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
use geo::{LineString, MultiLineString, MultiPolygon};
|
||||
|
||||
pub trait MergeExt {
|
||||
/// merge Container object
|
||||
fn merge(&mut self, other: &Self);
|
||||
/// merge container object, empty the other object
|
||||
fn merge_destructive(&mut self, other: &mut Self);
|
||||
}
|
||||
|
||||
impl MergeExt for LineString<f64> {
|
||||
fn merge(&mut self, other: &Self) {
|
||||
self.0.append(&mut other.0.clone());
|
||||
}
|
||||
fn merge_destructive(&mut self, other: &mut Self) {
|
||||
self.0.append(&mut other.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl MergeExt for MultiLineString<f64> {
|
||||
fn merge(&mut self, other: &Self) {
|
||||
self.0.append(&mut other.0.clone());
|
||||
}
|
||||
fn merge_destructive(&mut self, other: &mut Self) {
|
||||
self.0.append(&mut other.0);
|
||||
}
|
||||
}
|
||||
|
||||
impl MergeExt for MultiPolygon<f64> {
|
||||
fn merge(&mut self, other: &Self) {
|
||||
self.0.append(&mut other.0.clone());
|
||||
}
|
||||
fn merge_destructive(&mut self, other: &mut Self) {
|
||||
self.0.append(&mut other.0);
|
||||
}
|
||||
}
|
68
src/extensions/scale_ext.rs
Normal file
68
src/extensions/scale_ext.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use crate::extensions::translate_ext::ExplicitBoundingRect;
|
||||
use geo::algorithm::map_coords::MapCoords;
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::{CoordinateType, LineString, MultiLineString, MultiPolygon, Polygon};
|
||||
|
||||
pub trait ExplicitMapCoords<T> {
|
||||
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self;
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitMapCoords<T> for LineString<T> {
|
||||
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
||||
self.map_coords(func)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitMapCoords<T> for MultiLineString<T> {
|
||||
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
||||
self.map_coords(func)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitMapCoords<T> for MultiPolygon<T> {
|
||||
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
||||
self.map_coords(func)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitMapCoords<T> for Polygon<T> {
|
||||
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
||||
self.map_coords(func)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ScaleExt {
|
||||
/// scale object
|
||||
fn scale(&self, scale_x: f64, scale_y: f64) -> Self;
|
||||
/// scale object to given width (in 1:1 ratio)
|
||||
fn scale_to_width(&self, size: f64) -> Self;
|
||||
/// scale object to given height (in 1:1 ratio)
|
||||
fn scale_to_height(&self, size: f64) -> Self;
|
||||
}
|
||||
|
||||
impl<V> ScaleExt for V
|
||||
where
|
||||
V: ExplicitBoundingRect<f64> + ExplicitMapCoords<f64> + Translate<f64>,
|
||||
{
|
||||
fn scale(&self, scale_x: f64, scale_y: f64) -> Self {
|
||||
let bounding_rectangle = self.bounding().unwrap();
|
||||
let minimum_coordinates = bounding_rectangle.min();
|
||||
self.translate(-minimum_coordinates.x, -minimum_coordinates.y)
|
||||
.map_coordinates(|&(x, y)| (x * scale_x, y * scale_y))
|
||||
.translate(minimum_coordinates.x, minimum_coordinates.y)
|
||||
}
|
||||
|
||||
fn scale_to_width(&self, size: f64) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let diff = f64::abs(option.min().x - option.max().x);
|
||||
let scale = size / diff;
|
||||
self.scale(scale, scale)
|
||||
}
|
||||
|
||||
fn scale_to_height(&self, size: f64) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let diff = f64::abs(option.min().y - option.max().y);
|
||||
let scale = size / diff;
|
||||
self.scale(scale, scale)
|
||||
}
|
||||
}
|
87
src/extensions/translate_ext.rs
Normal file
87
src/extensions/translate_ext.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use geo::algorithm::bounding_rect::BoundingRect;
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::{CoordinateType, LineString, MultiLineString, MultiPolygon, Polygon, Rect};
|
||||
|
||||
/// wrapper for BoundingRect because of the Output type
|
||||
pub trait ExplicitBoundingRect<T>
|
||||
where
|
||||
T: CoordinateType,
|
||||
{
|
||||
fn bounding(&self) -> Option<Rect<T>>;
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for Polygon<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for MultiPolygon<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for LineString<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for MultiLineString<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Translate Extensions
|
||||
pub trait TranslateExt {
|
||||
/// translate the object to it's center
|
||||
fn translate_center(&self) -> Self;
|
||||
/// translate the object to it's center on the x aches
|
||||
fn translate_center_x(&self) -> Self;
|
||||
/// translate the object to it's center on the y aches
|
||||
fn translate_center_y(&self) -> Self;
|
||||
/// translate the object, so it touches the y aches
|
||||
fn translate_left(&self) -> Self;
|
||||
/// translate the object, so it touches the x aches
|
||||
fn translate_top(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<B> TranslateExt for B
|
||||
where
|
||||
B: ExplicitBoundingRect<f64> + Translate<f64>,
|
||||
{
|
||||
fn translate_center(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_center_x(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), 0.0)
|
||||
}
|
||||
|
||||
fn translate_center_y(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
self.translate(0.0, -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_left(&self) -> Self {
|
||||
let bounding = self.bounding().unwrap();
|
||||
self.translate(-bounding.min().x, 0.)
|
||||
}
|
||||
|
||||
fn translate_top(&self) -> Self {
|
||||
let bounding = self.bounding().unwrap();
|
||||
self.translate(0., -bounding.min().y)
|
||||
}
|
||||
}
|
140
src/font.rs
Normal file
140
src/font.rs
Normal file
|
@ -0,0 +1,140 @@
|
|||
// props to https://trmm.net/Asteroids_font
|
||||
// https://github.com/osresearch/vst/blob/master/teensyv/asteroids_font.c
|
||||
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::{Coordinate, LineString, MultiLineString};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AsteroidFont {
|
||||
letters: HashMap<char, Vec<Vec<(i32, i32)>>>,
|
||||
}
|
||||
|
||||
impl AsteroidFont {
|
||||
#[rustfmt::skip]
|
||||
pub fn new() -> Self {
|
||||
let mut letters = HashMap::new();
|
||||
letters.insert('0', vec![vec![(0, 0), (8, 0), (8, 12), (0, 12), (0, 0), (8, 12)]]);
|
||||
letters.insert('1', vec![vec![(4, 0), (4, 12), (3, 10)]]);
|
||||
letters.insert('2', vec![vec![(0, 12), (8, 12), (8, 7), (0, 5), (0, 0), (8, 0)]]);
|
||||
letters.insert('3', vec![vec![(0, 12), (8, 12), (8, 0), (0, 0), ], vec![(0, 6), (8, 6)]]);
|
||||
letters.insert('4', vec![vec![(0, 12), (0, 6), (8, 6), ], vec![(8, 12), (8, 0)]]);
|
||||
letters.insert('5', vec![vec![(0, 0), (8, 0), (8, 6), (0, 7), (0, 12), (8, 12)]]);
|
||||
letters.insert('6', vec![vec![(0, 12), (0, 0), (8, 0), (8, 5), (0, 7)]]);
|
||||
letters.insert('7', vec![vec![(0, 12), (8, 12), (8, 6), (4, 0)]]);
|
||||
letters.insert('8', vec![vec![(0, 0), (8, 0), (8, 12), (0, 12), (0, 0), ], vec![(0, 6), (8, 6)]]);
|
||||
letters.insert('9', vec![vec![(8, 0), (8, 12), (0, 12), (0, 7), (8, 5)]]);
|
||||
letters.insert(' ', vec![]);
|
||||
letters.insert('.', vec![vec![(3, 0), (4, 0)]]);
|
||||
letters.insert(',', vec![vec![(2, 0), (4, 2)]]);
|
||||
letters.insert('-', vec![vec![(2, 6), (6, 6)]]);
|
||||
letters.insert('+', vec![vec![(1, 6), (7, 6), ], vec![(4, 9), (4, 3)]]);
|
||||
letters.insert('!', vec![vec![(4, 0), (3, 2), (5, 2), (4, 0), ], vec![(4, 4), (4, 12)]]);
|
||||
letters.insert('#', vec![vec![(0, 4), (8, 4), (6, 2), (6, 10), (8, 8), (0, 8), (2, 10), (2, 2)]]);
|
||||
letters.insert('^', vec![vec![(2, 6), (4, 12), (6, 6)]]);
|
||||
letters.insert('=', vec![vec![(1, 4), (7, 4), ], vec![(1, 8), (7, 8)]]);
|
||||
letters.insert('*', vec![vec![(0, 0), (4, 12), (8, 0), (0, 8), (8, 8), (0, 0)]]);
|
||||
letters.insert('_', vec![vec![(0, 0), (8, 0)]]);
|
||||
letters.insert('/', vec![vec![(0, 0), (8, 12)]]);
|
||||
letters.insert('\\', vec![vec![(0, 12), (8, 0)]]);
|
||||
letters.insert('@', vec![vec![(8, 4), (4, 0), (0, 4), (0, 8), (4, 12), (8, 8), (4, 4), (3, 6)]]);
|
||||
letters.insert('$', vec![vec![(6, 2), (2, 6), (6, 10), ], vec![(4, 12), (4, 0)]]);
|
||||
letters.insert('&', vec![vec![(8, 0), (4, 12), (8, 8), (0, 4), (4, 0), (8, 4)]]);
|
||||
letters.insert('[', vec![vec![(6, 0), (2, 0), (2, 12), (6, 12)]]);
|
||||
letters.insert(']', vec![vec![(2, 0), (6, 0), (6, 12), (2, 12)]]);
|
||||
letters.insert('(', vec![vec![(6, 0), (2, 4), (2, 8), (6, 12)]]);
|
||||
letters.insert(')', vec![vec![(2, 0), (6, 4), (6, 8), (2, 12)]]);
|
||||
letters.insert('{', vec![vec![(6, 0), (4, 2), (4, 10), (6, 12), ], vec![(2, 6), (4, 6)]]);
|
||||
letters.insert('}', vec![vec![(4, 0), (6, 2), (6, 10), (4, 12), ], vec![(6, 6), (8, 6)]]);
|
||||
letters.insert('%', vec![vec![(0, 0), (8, 12), ], vec![(2, 10), (2, 8), ], vec![(6, 4), (6, 2)]]);
|
||||
letters.insert('<', vec![vec![(6, 0), (2, 6), (6, 12)]]);
|
||||
letters.insert('>', vec![vec![(2, 0), (6, 6), (2, 12)]]);
|
||||
letters.insert('|', vec![vec![(4, 0), (4, 5), ], vec![(4, 6), (4, 12)]]);
|
||||
letters.insert(':', vec![vec![(4, 9), (4, 7), ], vec![(4, 5), (4, 3)]]);
|
||||
letters.insert(';', vec![vec![(4, 9), (4, 7), ], vec![(4, 5), (1, 2)]]);
|
||||
letters.insert('"', vec![vec![(2, 10), (2, 6), ], vec![(6, 10), (6, 6)]]);
|
||||
letters.insert('\'', vec![vec![(2, 6), (6, 10)]]);
|
||||
letters.insert('`', vec![vec![(2, 10), (6, 6)]]);
|
||||
letters.insert('~', vec![vec![(0, 4), (2, 8), (6, 4), (8, 8)]]);
|
||||
letters.insert('?', vec![vec![(0, 8), (4, 12), (8, 8), (4, 4), ], vec![(4, 1), (4, 0)]]);
|
||||
letters.insert('a', vec![vec![(0, 0), (0, 8), (4, 12), (8, 8), (8, 0), ], vec![(0, 4), (8, 4)]]);
|
||||
letters.insert('b', vec![vec![(0, 0), (0, 12), (4, 12), (8, 10), (4, 6), (8, 2), (4, 0), (0, 0)]]);
|
||||
letters.insert('c', vec![vec![(8, 0), (0, 0), (0, 12), (8, 12)]]);
|
||||
letters.insert('d', vec![vec![(0, 0), (0, 12), (4, 12), (8, 8), (8, 4), (4, 0), (0, 0)]]);
|
||||
letters.insert('e', vec![vec![(8, 0), (0, 0), (0, 12), (8, 12), ], vec![(0, 6), (6, 6)]]);
|
||||
letters.insert('f', vec![vec![(0, 0), (0, 12), (8, 12), ], vec![(0, 6), (6, 6)]]);
|
||||
letters.insert('g', vec![vec![(6, 6), (8, 4), (8, 0), (0, 0), (0, 12), (8, 12)]]);
|
||||
letters.insert('h', vec![vec![(0, 0), (0, 12), ], vec![(0, 6), (8, 6), ], vec![(8, 12), (8, 0)]]);
|
||||
letters.insert('i', vec![vec![(0, 0), (8, 0), ], vec![(4, 0), (4, 12), ], vec![(0, 12), (8, 12)]]);
|
||||
letters.insert('j', vec![vec![(0, 4), (4, 0), (8, 0), (8, 12)]]);
|
||||
letters.insert('k', vec![vec![(0, 0), (0, 12), ], vec![(8, 12), (0, 6), (6, 0)]]);
|
||||
letters.insert('l', vec![vec![(8, 0), (0, 0), (0, 12)]]);
|
||||
letters.insert('m', vec![vec![(0, 0), (0, 12), (4, 8), (8, 12), (8, 0)]]);
|
||||
letters.insert('n', vec![vec![(0, 0), (0, 12), (8, 0), (8, 12)]]);
|
||||
letters.insert('o', vec![vec![(0, 0), (0, 12), (8, 12), (8, 0), (0, 0)]]);
|
||||
letters.insert('p', vec![vec![(0, 0), (0, 12), (8, 12), (8, 6), (0, 5)]]);
|
||||
letters.insert('q', vec![vec![(0, 0), (0, 12), (8, 12), (8, 4), (0, 0), ], vec![(4, 4), (8, 0)]]);
|
||||
letters.insert('r', vec![vec![(0, 0), (0, 12), (8, 12), (8, 6), (0, 5), ], vec![(4, 5), (8, 0)]]);
|
||||
letters.insert('s', vec![vec![(0, 2), (2, 0), (8, 0), (8, 5), (0, 7), (0, 12), (6, 12), (8, 10)]]);
|
||||
letters.insert('t', vec![vec![(0, 12), (8, 12), ], vec![(4, 12), (4, 0)]]);
|
||||
letters.insert('u', vec![vec![(0, 12), (0, 2), (4, 0), (8, 2), (8, 12)]]);
|
||||
letters.insert('v', vec![vec![(0, 12), (4, 0), (8, 12)]]);
|
||||
letters.insert('w', vec![vec![(0, 12), (2, 0), (4, 4), (6, 0), (8, 12)]]);
|
||||
letters.insert('x', vec![vec![(0, 0), (8, 12), ], vec![(0, 12), (8, 0)]]);
|
||||
letters.insert('y', vec![vec![(0, 12), (4, 6), (8, 12), ], vec![(4, 6), (4, 0)]]);
|
||||
letters.insert('z', vec![vec![(0, 12), (8, 12), (0, 0), (8, 0), ], vec![(2, 6), (6, 6)]]);
|
||||
AsteroidFont {letters }
|
||||
}
|
||||
|
||||
pub fn get_letter(&self, letter: &char, size: f64) -> Vec<LineString<f64>> {
|
||||
let letter_coordinates = self.letters.get(&letter.to_ascii_lowercase()).unwrap();
|
||||
let mut polygons: Vec<LineString<f64>> = Vec::new();
|
||||
for letter_part in letter_coordinates.iter() {
|
||||
let coordinates: Vec<Coordinate<f64>> = letter_part
|
||||
.iter()
|
||||
.map(|&(x, y)| Coordinate {
|
||||
x: x as f64 * size / 12.,
|
||||
y: (12. - y as f64) * size / 12.,
|
||||
})
|
||||
.collect();
|
||||
polygons.push(LineString(coordinates));
|
||||
}
|
||||
polygons
|
||||
}
|
||||
|
||||
/// size of space (per letter)
|
||||
pub fn get_text_scale_factor(&self, size: f64) -> (f64, f64) {
|
||||
let scale_factor = size / 12.;
|
||||
(10.2 * scale_factor, 14.2 * scale_factor)
|
||||
}
|
||||
|
||||
pub fn get_text(
|
||||
&self,
|
||||
text: String,
|
||||
size: f64,
|
||||
direction: FontDirection,
|
||||
) -> MultiLineString<f64> {
|
||||
let mut letters: Vec<LineString<f64>> = Vec::new();
|
||||
let mut count = 0.;
|
||||
for char in text.chars() {
|
||||
let letter = self.get_letter(&char, size);
|
||||
let (x_translate_factor, y_translate_factor) = self.get_text_scale_factor(size);
|
||||
for character in letter.iter() {
|
||||
match direction {
|
||||
FontDirection::LeftRight => {
|
||||
letters.push(character.translate(count * x_translate_factor, 0.))
|
||||
}
|
||||
FontDirection::TopDown => {
|
||||
letters.push(character.translate(0., count * y_translate_factor))
|
||||
}
|
||||
}
|
||||
}
|
||||
count = count + 1.;
|
||||
}
|
||||
MultiLineString(letters)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FontDirection {
|
||||
LeftRight,
|
||||
TopDown,
|
||||
}
|
13
src/lib.rs
13
src/lib.rs
|
@ -1,8 +1,15 @@
|
|||
mod context;
|
||||
pub use crate::context::Context;
|
||||
|
||||
mod multipolygon_ext;
|
||||
pub use crate::multipolygon_ext::MultiPolygonExt;
|
||||
mod extensions;
|
||||
pub use crate::extensions::merge_ext::MergeExt;
|
||||
pub use crate::extensions::scale_ext::ScaleExt;
|
||||
pub use crate::extensions::translate_ext::TranslateExt;
|
||||
|
||||
mod svg;
|
||||
pub use crate::svg::load_multipolgon_from_svg;
|
||||
pub use crate::svg::load_multipolygon_from_svg;
|
||||
pub use crate::svg::load_multipolygon_from_svg_include;
|
||||
|
||||
mod font;
|
||||
pub use crate::font::AsteroidFont;
|
||||
pub use crate::font::FontDirection;
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
use geo::algorithm::bounding_rect::BoundingRect;
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::Polygon;
|
||||
use geo_types::{Coordinate, LineString, MultiPolygon};
|
||||
|
||||
pub trait MultiPolygonExt {
|
||||
fn translate_center(&self) -> Self;
|
||||
fn translate_center_x(&self) -> Self;
|
||||
fn translate_center_y(&self) -> Self;
|
||||
fn scale_to_width(&self, size: f64) -> Self;
|
||||
fn scale(&self, factor: f64) -> Self;
|
||||
}
|
||||
|
||||
impl MultiPolygonExt for MultiPolygon<f64> {
|
||||
fn translate_center(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_center_x(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), 0.0)
|
||||
}
|
||||
|
||||
fn translate_center_y(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
self.translate(0.0, -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn scale_to_width(&self, size: f64) -> Self {
|
||||
// let ((x_min, y_min), (x_max, _)) = self.get_min_max_rectangle();
|
||||
let option = self.bounding_rect().unwrap();
|
||||
|
||||
let diff = f64::abs(option.min().x - option.max().x);
|
||||
let scale = size / diff;
|
||||
self.scale(scale)
|
||||
}
|
||||
|
||||
fn scale(&self, factor: f64) -> Self {
|
||||
let bounding_rectangle = self.bounding_rect().unwrap();
|
||||
let zeroed_multi_polygons =
|
||||
self.translate(-bounding_rectangle.min().x, -bounding_rectangle.min().y);
|
||||
let mut new_polygons: Vec<Polygon<f64>> = Vec::new();
|
||||
for polygon in zeroed_multi_polygons.iter() {
|
||||
// map interiors
|
||||
let mut interiors: Vec<LineString<f64>> = Vec::new();
|
||||
for interior_line_string in polygon.interiors().to_vec() {
|
||||
let mut new_line_string: Vec<Coordinate<f64>> = Vec::new();
|
||||
for point in interior_line_string.into_points() {
|
||||
new_line_string.push(Coordinate {
|
||||
x: point.x() * factor,
|
||||
y: point.y() * factor,
|
||||
});
|
||||
}
|
||||
interiors.push(LineString::from(new_line_string));
|
||||
}
|
||||
// map exterior
|
||||
let mut new_line_string: Vec<Coordinate<f64>> = Vec::new();
|
||||
for point in polygon.exterior().clone().into_points() {
|
||||
new_line_string.push(Coordinate {
|
||||
x: point.x() * factor,
|
||||
y: point.y() * factor,
|
||||
});
|
||||
}
|
||||
let exterior = LineString::from(new_line_string);
|
||||
new_polygons.push(Polygon::new(exterior, interiors));
|
||||
}
|
||||
MultiPolygon::from(new_polygons)
|
||||
.translate(bounding_rectangle.min().x, bounding_rectangle.min().y)
|
||||
}
|
||||
}
|
22
src/svg.rs
22
src/svg.rs
|
@ -3,12 +3,28 @@ use geo_types::{Coordinate, LineString, MultiPolygon, Polygon};
|
|||
use std::error::Error;
|
||||
use svg::node::element::tag::Path;
|
||||
use svg::parser::Event;
|
||||
use svg::Parser;
|
||||
|
||||
/// load a multipolygon dynamically at runtime
|
||||
pub fn load_multipolygon_from_svg(path: &str) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let mut content = String::new();
|
||||
let parser = svg::open(path, &mut content)?;
|
||||
parse_svg_to_multipolygon(parser)
|
||||
}
|
||||
|
||||
/// load a multipolygon statically at compiletime
|
||||
/// with include_str!
|
||||
pub fn load_multipolygon_from_svg_include(
|
||||
content: &str,
|
||||
) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let parser = svg::read(content)?;
|
||||
parse_svg_to_multipolygon(parser)
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub fn load_multipolgon_from_svg(path: &str) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let mut content = String::new();
|
||||
fn parse_svg_to_multipolygon(parser: Parser) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let mut result: Vec<Polygon<f64>> = Vec::new();
|
||||
for event in svg::open(path, &mut content)? {
|
||||
for event in parser {
|
||||
match event {
|
||||
Event::Tag(Path, _, attributes) => {
|
||||
let data = attributes.get("d").unwrap();
|
||||
|
|
Loading…
Reference in a new issue