diff --git a/Cargo.lock b/Cargo.lock
index bf3ac0b..d24a92d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "addr2line"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
[[package]]
name = "aho-corasick"
version = "0.7.20"
@@ -11,11 +26,38 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "anyhow"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "arc-swap"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "ashpd"
@@ -31,7 +73,7 @@ dependencies = [
"gdk4-x11",
"gtk4",
"once_cell",
- "rand",
+ "rand 0.8.5",
"serde",
"serde_repr",
"url",
@@ -40,13 +82,12 @@ dependencies = [
[[package]]
name = "async-broadcast"
-version = "0.5.0"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95"
+checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
dependencies = [
"event-listener",
"futures-core",
- "parking_lot",
]
[[package]]
@@ -111,12 +152,11 @@ dependencies = [
[[package]]
name = "async-lock"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
+checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
dependencies = [
"event-listener",
- "futures-lite",
]
[[package]]
@@ -164,9 +204,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
[[package]]
name = "async-trait"
-version = "0.1.64"
+version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
+checksum = "095183a3539c7c7649b2beb87c2d3f0591f3a7fed07761cc546d244e27e0238c"
dependencies = [
"proc-macro2",
"quote",
@@ -185,7 +225,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -196,6 +236,27 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "backtrace"
+version = "0.3.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bit_field"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -243,6 +304,12 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
+[[package]]
+name = "bytemuck"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+
[[package]]
name = "byteorder"
version = "1.4.3"
@@ -257,7 +324,7 @@ checksum = "a8af54f5d48af1226928adc1f57edd22f5df1349e7da1fc96ae15cf43db0e871"
dependencies = [
"bitflags",
"cairo-sys-rs",
- "glib 0.17.1",
+ "glib 0.17.2",
"libc",
"once_cell",
"thiserror",
@@ -269,16 +336,16 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55382a01d30e5e53f185eee269124f5e21ab526595b872751278dfbb463594e"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"libc",
"system-deps",
]
[[package]]
name = "camino"
-version = "1.1.2"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055"
+checksum = "6031a462f977dd38968b6f23378356512feeace69cef817e1a4475108093cec3"
dependencies = [
"serde",
]
@@ -300,11 +367,17 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
dependencies = [
"camino",
"cargo-platform",
- "semver 1.0.16",
+ "semver",
"serde",
"serde_json",
]
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
[[package]]
name = "cc"
version = "1.0.79"
@@ -326,6 +399,83 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+[[package]]
+name = "chrono"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-integer",
+ "num-traits",
+ "time",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "clap"
+version = "4.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5"
+dependencies = [
+ "bitflags",
+ "clap_derive",
+ "clap_lex",
+ "is-terminal",
+ "once_cell",
+ "strsim",
+ "termcolor",
+]
+
+[[package]]
+name = "clap_complete"
+version = "4.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "501ff0a401473ea1d4c3b125ff95506b62c5bc5768d818634195fbb7c4ad5ff4"
+dependencies = [
+ "clap",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "color_quant"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+
[[package]]
name = "concurrent-queue"
version = "2.1.0"
@@ -335,6 +485,18 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "convert_case"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
[[package]]
name = "cpufeatures"
version = "0.2.5"
@@ -345,14 +507,63 @@ dependencies = [
]
[[package]]
-name = "crossbeam-utils"
-version = "0.8.14"
+name = "crc32fast"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset 0.8.0",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -363,6 +574,33 @@ dependencies = [
"typenum",
]
+[[package]]
+name = "cssparser"
+version = "0.29.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa"
+dependencies = [
+ "cssparser-macros",
+ "dtoa-short",
+ "itoa",
+ "matches",
+ "phf 0.10.1",
+ "proc-macro2",
+ "quote",
+ "smallvec",
+ "syn",
+]
+
+[[package]]
+name = "cssparser-macros"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "ctor"
version = "0.1.26"
@@ -373,6 +611,56 @@ dependencies = [
"syn",
]
+[[package]]
+name = "cxx"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "data-url"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5"
+
[[package]]
name = "derivative"
version = "2.2.0"
@@ -384,6 +672,19 @@ dependencies = [
"syn",
]
+[[package]]
+name = "derive_more"
+version = "0.99.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+dependencies = [
+ "convert_case",
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "syn",
+]
+
[[package]]
name = "digest"
version = "0.10.6"
@@ -420,6 +721,91 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+[[package]]
+name = "dtoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
+
+[[package]]
+name = "dtoa-short"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6"
+dependencies = [
+ "dtoa",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "encoding"
+version = "0.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
+dependencies = [
+ "encoding-index-japanese",
+ "encoding-index-korean",
+ "encoding-index-simpchinese",
+ "encoding-index-singlebyte",
+ "encoding-index-tradchinese",
+]
+
+[[package]]
+name = "encoding-index-japanese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-korean"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-simpchinese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-singlebyte"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding-index-tradchinese"
+version = "1.20141219.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
+dependencies = [
+ "encoding_index_tests",
+]
+
+[[package]]
+name = "encoding_index_tests"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
+
[[package]]
name = "enumflags2"
version = "0.7.5"
@@ -441,6 +827,17 @@ dependencies = [
"syn",
]
+[[package]]
+name = "enumn"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88bcb3a067a6555d577aba299e75eff9942da276e6506fc6274327daa026132"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "env_logger"
version = "0.7.1"
@@ -490,6 +887,22 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+[[package]]
+name = "exr"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8af5ef47e2ed89d23d0ecbc1b681b30390069de70260937877514377fc24feb"
+dependencies = [
+ "bit_field",
+ "flume",
+ "half",
+ "lebe",
+ "miniz_oxide",
+ "smallvec",
+ "threadpool",
+ "zune-inflate",
+]
+
[[package]]
name = "fastrand"
version = "1.9.0"
@@ -501,14 +914,46 @@ dependencies = [
[[package]]
name = "field-offset"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
+checksum = "a3cf3a800ff6e860c863ca6d4b16fd999db8b752819c1606884047b73e468535"
dependencies = [
- "memoffset",
+ "memoffset 0.8.0",
"rustc_version",
]
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "float-cmp"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "flume"
+version = "0.10.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "nanorand",
+ "pin-project",
+ "spin",
+]
+
[[package]]
name = "form_urlencoded"
version = "1.1.0"
@@ -518,6 +963,22 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "four-cc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92d73a076bdabd78c2f9045dba1b90664a655fa8372581c238596e1eb3a5e1b7"
+
+[[package]]
+name = "futf"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
+dependencies = [
+ "mac",
+ "new_debug_unreachable",
+]
+
[[package]]
name = "futures"
version = "0.3.26"
@@ -622,6 +1083,15 @@ dependencies = [
"slab",
]
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "gdk-pixbuf"
version = "0.17.0"
@@ -630,8 +1100,8 @@ checksum = "b023fbe0c6b407bd3d9805d107d9800da3829dc5a676653210f1d5f16d7f59bf"
dependencies = [
"bitflags",
"gdk-pixbuf-sys",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"libc",
"once_cell",
]
@@ -643,7 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b41bd2b44ed49d99277d3925652a163038bd5ed943ec9809338ffb2f4391e3b"
dependencies = [
"gio-sys 0.17.0",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"libc",
"system-deps",
@@ -651,30 +1121,30 @@ dependencies = [
[[package]]
name = "gdk4"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4887e17b6926db51f1e538d871a8b1f5ceb5dfa3bd0034dc42ec355b390d8f"
+checksum = "e5042053ee765aeef08d9d7e3f0f1e36a4d37f1659b3f93ad3d6997515dbb64a"
dependencies = [
"bitflags",
"cairo-rs",
"gdk-pixbuf",
"gdk4-sys",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"libc",
"pango",
]
[[package]]
name = "gdk4-sys"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4993c019bf03d18137c00ddafb2b23e73f7cbb45ae244f52af2542a3f4a9452"
+checksum = "14f0fb00507af1e9299681dd09965f720e2b5ea95536d49a5681e8994ef10c7a"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys 0.17.0",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"libc",
"pango-sys",
@@ -684,49 +1154,49 @@ dependencies = [
[[package]]
name = "gdk4-wayland"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f6101812fc251eeb7ba5babe62b291505a8e6f64326929b657923049e39acee"
+checksum = "4d34175f400cfc1dc20443a97184d8366e78b16ae488f6ad208c44f710713d9a"
dependencies = [
"gdk4",
"gdk4-wayland-sys",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"libc",
]
[[package]]
name = "gdk4-wayland-sys"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9b33e54388919cb9f289075202eefeee9b4633188d835ce77d81224dc4cd219"
+checksum = "d3a7589f15d81c946598b31aa21113011b2465c5e4459f7b34d4895168f5a3e7"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"libc",
"system-deps",
]
[[package]]
name = "gdk4-x11"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f843aaaa34487384060dd86ef9737ebd5d6dbd90e75d73991f3b706aee645b13"
+checksum = "8c2cb4d8362649a35490098008235f242eedff719c6340178a80c3c03ea4dd5a"
dependencies = [
"gdk4",
"gdk4-x11-sys",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"libc",
]
[[package]]
name = "gdk4-x11-sys"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eafef0f400d191b6176144e7c7d41c8027232d563e1def5460b9328638eecdd"
+checksum = "880be6ce14b75f173525d6e1dd62342d7189a01fab1686c0c6e1d58312acf3f1"
dependencies = [
"gdk4-sys",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"libc",
"system-deps",
]
@@ -741,6 +1211,17 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
[[package]]
name = "getrandom"
version = "0.2.8"
@@ -748,8 +1229,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
+ "js-sys",
"libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
]
[[package]]
@@ -772,6 +1255,22 @@ dependencies = [
"temp-dir",
]
+[[package]]
+name = "gif"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
+dependencies = [
+ "color_quant",
+ "weezl",
+]
+
+[[package]]
+name = "gimli"
+version = "0.27.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
+
[[package]]
name = "gio"
version = "0.15.12"
@@ -791,9 +1290,9 @@ dependencies = [
[[package]]
name = "gio"
-version = "0.17.0"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1981edf8679d2f2c8ec3120015867f45aa0a1c2d5e3e129ca2f7dda174d3d2a9"
+checksum = "65acfc24267314eee46f49e0a531e08fd6c3025040d1cfb4a7cd8e41c5e06116"
dependencies = [
"bitflags",
"futures-channel",
@@ -801,7 +1300,7 @@ dependencies = [
"futures-io",
"futures-util",
"gio-sys 0.17.0",
- "glib 0.17.1",
+ "glib 0.17.2",
"libc",
"once_cell",
"pin-project-lite",
@@ -828,7 +1327,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5d3076ecb86c8c3a672c9843d6232b3a344fb81d304d0ba1ac64b23343efa46"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"libc",
"system-deps",
@@ -857,9 +1356,9 @@ dependencies = [
[[package]]
name = "glib"
-version = "0.17.1"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91b429154ec5943185aeeaf79e646297567b6a056965f1e89da2657a0e23255b"
+checksum = "a78b6a0901e258cb03c761ca94c84d519427ede489cae12cd5ba0d7d584e69e9"
dependencies = [
"bitflags",
"futures-channel",
@@ -868,8 +1367,8 @@ dependencies = [
"futures-task",
"futures-util",
"gio-sys 0.17.0",
- "glib-macros 0.17.1",
- "glib-sys 0.17.0",
+ "glib-macros 0.17.2",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"libc",
"memchr",
@@ -895,9 +1394,9 @@ dependencies = [
[[package]]
name = "glib-macros"
-version = "0.17.1"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bc80ac951300ca288dd9ab3863743c37a608fb0e5ca12863495640ec6b781ab"
+checksum = "55e93d79ed130f0f0b58bc0aa29fb0e40c9dfd63997fec51f8adf780d1520bc4"
dependencies = [
"anyhow",
"heck",
@@ -920,9 +1419,9 @@ dependencies = [
[[package]]
name = "glib-sys"
-version = "0.17.0"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ddcb73fa8236277bedadaaadb76aef49c85d66340f83bece244f46c2d4f0e01"
+checksum = "72a0985cf568e18cf63b443c9a14f4bdaa947fed7437476000dba84926a20b25"
dependencies = [
"libc",
"system-deps",
@@ -963,7 +1462,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a0155d388840c77d61b033b66ef4f9bc7f4133d83df83572d6b4fb234a3be7d"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"libc",
"system-deps",
]
@@ -974,7 +1473,7 @@ version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21cf11565bb0e4dfc2f99d4775b6c329f0d40a2cff9c0066214d31a0e1b46256"
dependencies = [
- "glib 0.17.1",
+ "glib 0.17.2",
"graphene-sys",
"libc",
]
@@ -985,7 +1484,7 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf80a4849a8d9565410a8fec6fc3678e9c617f4ac7be182ca55ab75016e07af9"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"libc",
"pkg-config",
"system-deps",
@@ -993,14 +1492,14 @@ dependencies = [
[[package]]
name = "gsk4"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "432f981e4ea9f0739a5731d8a649acb794a3a729d2254e559ce7d613b17caf95"
+checksum = "2fa9cd285a72a95124b65c069a9cb1b8fb8e310be71783404c39fccf3bf7774c"
dependencies = [
"bitflags",
"cairo-rs",
"gdk4",
- "glib 0.17.1",
+ "glib 0.17.2",
"graphene-rs",
"gsk4-sys",
"libc",
@@ -1009,13 +1508,13 @@ dependencies = [
[[package]]
name = "gsk4-sys"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "096cb59175b0915ebf69c05a45263c0c989bd8537b8f2169912d0de644ba6a76"
+checksum = "5a445ae1e50cbf181a1d5c61b920a7e7e8657b96e0ecdbbf8911a86fad462a32"
dependencies = [
"cairo-sys-rs",
"gdk4-sys",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"graphene-sys",
"libc",
@@ -1031,9 +1530,9 @@ checksum = "da5bf7748fd4cd0b2490df8debcc911809dbcbee4ece9531b96c29a9c729de5a"
[[package]]
name = "gtk4"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73421200ad9c3919d0720779b345b05d31a6ce9998e74fc27012f12580822e46"
+checksum = "e47dca53cb1a8ae3006e869b5711ae7370180db537f6d98e3bcaf23fabfd911f"
dependencies = [
"bitflags",
"cairo-rs",
@@ -1041,8 +1540,8 @@ dependencies = [
"futures-channel",
"gdk-pixbuf",
"gdk4",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"graphene-rs",
"gsk4",
"gtk4-macros",
@@ -1069,15 +1568,15 @@ dependencies = [
[[package]]
name = "gtk4-sys"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13cf3bc9559f71963c957eb639060b643e1276ae47b892ef6091d5bc15c3e1b"
+checksum = "65463dc801460e498d5e7ffa6e9ae2cfbed7d05fabd1ca5a8d024adbc89eeda6"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk4-sys",
"gio-sys 0.17.0",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"graphene-sys",
"gsk4-sys",
@@ -1099,6 +1598,15 @@ dependencies = [
"system-deps",
]
+[[package]]
+name = "half"
+version = "2.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
+dependencies = [
+ "crunchy",
+]
+
[[package]]
name = "hashbrown"
version = "0.12.3"
@@ -1120,6 +1628,21 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
[[package]]
name = "hex"
version = "0.4.3"
@@ -1135,6 +1658,30 @@ dependencies = [
"quick-error",
]
+[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
[[package]]
name = "idna"
version = "0.3.0"
@@ -1145,6 +1692,24 @@ dependencies = [
"unicode-normalization",
]
+[[package]]
+name = "image"
+version = "0.24.5"
+source = "git+https://github.com/image-rs/image.git#55732d14434cf639f2e79890f43a1d48bfb8617b"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "exr",
+ "gif",
+ "jpeg-decoder",
+ "num-rational",
+ "num-traits",
+ "png",
+ "qoi",
+ "tiff",
+]
+
[[package]]
name = "indexmap"
version = "1.9.2"
@@ -1175,10 +1740,40 @@ dependencies = [
]
[[package]]
-name = "itoa"
-version = "1.0.5"
+name = "is-terminal"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "jpeg-decoder"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
+dependencies = [
+ "rayon",
+]
[[package]]
name = "js-sys"
@@ -1207,12 +1802,24 @@ dependencies = [
"log",
]
+[[package]]
+name = "language-tags"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
+
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+[[package]]
+name = "lebe"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
+
[[package]]
name = "libadwaita"
version = "0.3.1"
@@ -1223,8 +1830,8 @@ dependencies = [
"futures-channel",
"gdk-pixbuf",
"gdk4",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"gtk4",
"libadwaita-sys",
"libc",
@@ -1240,7 +1847,7 @@ checksum = "0727b85b4fe2b1bed5ac90df6343de15cbf8118bfb96d7c3cc1512681a4b34ac"
dependencies = [
"gdk4-sys",
"gio-sys 0.17.0",
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"gtk4-sys",
"libc",
@@ -1267,6 +1874,77 @@ dependencies = [
"libc",
]
+[[package]]
+name = "libheif-rs"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "493fd0e4e813e9262b3eb76f5937385e979ed26733ac770c9ecb7bb005ba444a"
+dependencies = [
+ "enumn",
+ "four-cc",
+ "libheif-sys",
+]
+
+[[package]]
+name = "libheif-sys"
+version = "1.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6af8b7a4151ae10f6d2e8684f7172c43f09c0258c84190fd9704422588ceec63"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "librsvg"
+version = "2.55.91"
+source = "git+https://gitlab.gnome.org/GNOME/librsvg.git#1f11b3c236c374c58d929baafa0841fef59c4155"
+dependencies = [
+ "anyhow",
+ "byteorder",
+ "cairo-rs",
+ "cast",
+ "chrono",
+ "clap",
+ "clap_complete",
+ "cssparser",
+ "data-url",
+ "encoding",
+ "float-cmp",
+ "gdk-pixbuf",
+ "gio 0.17.2",
+ "glib 0.17.2",
+ "itertools",
+ "language-tags",
+ "libc",
+ "locale_config",
+ "markup5ever",
+ "nalgebra",
+ "num-traits",
+ "once_cell",
+ "pango",
+ "pangocairo",
+ "rayon",
+ "rctree",
+ "regex",
+ "rgb",
+ "selectors",
+ "string_cache",
+ "system-deps",
+ "thiserror",
+ "tinyvec",
+ "url",
+ "xml5ever",
+]
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
@@ -1311,26 +1989,37 @@ name = "loupe"
version = "0.1.0"
dependencies = [
"anyhow",
+ "arc-swap",
"ashpd",
"async-global-executor",
"async-std",
"futures",
"futures-channel",
"gettext-rs",
- "gio 0.17.0",
+ "gio 0.17.2",
"gtk-macros",
"gtk4",
+ "image",
"indexmap",
"kamadak-exif",
"libadwaita",
"libgweather",
+ "libheif-rs",
+ "librsvg",
"log",
"once_cell",
"pretty_env_logger",
+ "safe-transmute",
"svg_metadata",
"url",
]
+[[package]]
+name = "mac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+
[[package]]
name = "malloc_buf"
version = "0.0.6"
@@ -1340,6 +2029,35 @@ dependencies = [
"libc",
]
+[[package]]
+name = "markup5ever"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
+dependencies = [
+ "log",
+ "phf 0.10.1",
+ "phf_codegen 0.10.0",
+ "string_cache",
+ "string_cache_codegen",
+ "tendril",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
+
+[[package]]
+name = "matrixmultiply"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84"
+dependencies = [
+ "rawpointer",
+]
+
[[package]]
name = "memchr"
version = "2.5.0"
@@ -1355,12 +2073,72 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
[[package]]
name = "mutate_once"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b"
+[[package]]
+name = "nalgebra"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6515c882ebfddccaa73ead7320ca28036c4bc84c9bcca3cc0cbba8efe89223a"
+dependencies = [
+ "approx",
+ "matrixmultiply",
+ "nalgebra-macros",
+ "num-complex",
+ "num-rational",
+ "num-traits",
+ "simba",
+ "typenum",
+]
+
+[[package]]
+name = "nalgebra-macros"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "nanorand"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
+dependencies = [
+ "getrandom 0.2.8",
+]
+
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+
[[package]]
name = "nix"
version = "0.25.1"
@@ -1371,17 +2149,63 @@ dependencies = [
"bitflags",
"cfg-if",
"libc",
- "memoffset",
+ "memoffset 0.6.5",
"pin-utils",
]
[[package]]
-name = "nom8"
-version = "0.2.0"
+name = "nodrop"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
+checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
+
+[[package]]
+name = "num-complex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
dependencies = [
- "memchr",
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
]
[[package]]
@@ -1413,6 +2237,15 @@ dependencies = [
"objc",
]
+[[package]]
+name = "object"
+version = "0.30.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "once_cell"
version = "1.17.1"
@@ -1429,6 +2262,12 @@ dependencies = [
"pin-project-lite",
]
+[[package]]
+name = "os_str_bytes"
+version = "6.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
+
[[package]]
name = "pango"
version = "0.17.0"
@@ -1436,8 +2275,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243c048be90312220fb3bd578176eed8290568274a93c95040289d39349384bc"
dependencies = [
"bitflags",
- "gio 0.17.0",
- "glib 0.17.1",
+ "gio 0.17.2",
+ "glib 0.17.2",
"libc",
"once_cell",
"pango-sys",
@@ -1449,12 +2288,39 @@ version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4293d0f0b5525eb5c24734d30b0ed02cd02aa734f216883f376b54de49625de8"
dependencies = [
- "glib-sys 0.17.0",
+ "glib-sys 0.17.2",
"gobject-sys 0.17.0",
"libc",
"system-deps",
]
+[[package]]
+name = "pangocairo"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2feeb7ea7874507f83f5e7ba869c54e321959431c8fbd70d4b735c8b15d90506"
+dependencies = [
+ "bitflags",
+ "cairo-rs",
+ "glib 0.17.2",
+ "libc",
+ "pango",
+ "pangocairo-sys",
+]
+
+[[package]]
+name = "pangocairo-sys"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71abd374a8322e2e382039ff2e020c4cc9ef2e12ea488e38d9cec4a55e296470"
+dependencies = [
+ "cairo-sys-rs",
+ "glib-sys 0.17.2",
+ "libc",
+ "pango-sys",
+ "system-deps",
+]
+
[[package]]
name = "parking"
version = "2.0.0"
@@ -1484,6 +2350,12 @@ dependencies = [
"windows-sys 0.45.0",
]
+[[package]]
+name = "paste"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
+
[[package]]
name = "percent-encoding"
version = "2.2.0"
@@ -1491,13 +2363,115 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
-name = "pest"
-version = "2.5.5"
+name = "phf"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660"
+checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
- "thiserror",
- "ucd-trie",
+ "phf_shared 0.8.0",
+]
+
+[[package]]
+name = "phf"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
+dependencies = [
+ "phf_macros",
+ "phf_shared 0.10.0",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
+dependencies = [
+ "phf_generator 0.8.0",
+ "phf_shared 0.8.0",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
+dependencies = [
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
+dependencies = [
+ "phf_shared 0.8.0",
+ "rand 0.7.3",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
+dependencies = [
+ "phf_shared 0.10.0",
+ "rand 0.8.5",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
+dependencies = [
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
@@ -1518,6 +2492,18 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+[[package]]
+name = "png"
+version = "0.17.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
+dependencies = [
+ "bitflags",
+ "crc32fast",
+ "flate2",
+ "miniz_oxide",
+]
+
[[package]]
name = "polling"
version = "2.5.2"
@@ -1538,6 +2524,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
@@ -1550,9 +2542,9 @@ dependencies = [
[[package]]
name = "proc-macro-crate"
-version = "1.3.0"
+version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
dependencies = [
"once_cell",
"toml_edit",
@@ -1582,6 +2574,12 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
[[package]]
name = "proc-macro2"
version = "1.0.51"
@@ -1602,6 +2600,15 @@ dependencies = [
"unicase",
]
+[[package]]
+name = "qoi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
+dependencies = [
+ "bytemuck",
+]
+
[[package]]
name = "quick-error"
version = "1.2.3"
@@ -1626,6 +2633,20 @@ dependencies = [
"proc-macro2",
]
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc",
+ "rand_pcg",
+]
+
[[package]]
name = "rand"
version = "0.8.5"
@@ -1633,8 +2654,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
- "rand_chacha",
- "rand_core",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
]
[[package]]
@@ -1644,7 +2675,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
- "rand_core",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
]
[[package]]
@@ -1653,9 +2693,61 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom",
+ "getrandom 0.2.8",
]
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rawpointer"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "rctree"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f"
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -1671,7 +2763,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
- "getrandom",
+ "getrandom 0.2.8",
"redox_syscall",
"thiserror",
]
@@ -1693,6 +2785,15 @@ version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+[[package]]
+name = "rgb"
+version = "0.8.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59"
+dependencies = [
+ "bytemuck",
+]
+
[[package]]
name = "roxmltree"
version = "0.18.0"
@@ -1703,12 +2804,18 @@ dependencies = [
]
[[package]]
-name = "rustc_version"
-version = "0.3.3"
+name = "rustc-demangle"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
- "semver 0.11.0",
+ "semver",
]
[[package]]
@@ -1727,9 +2834,24 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "safe-transmute"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98a01dab6acf992653be49205bdd549f32f17cb2803e8eacf1560bf97259aae8"
+
+[[package]]
+name = "safe_arch"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529"
+dependencies = [
+ "bytemuck",
+]
[[package]]
name = "same-file"
@@ -1747,12 +2869,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
-name = "semver"
-version = "0.11.0"
+name = "scratch"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+checksum = "5d5e082f6ea090deaf0e6dd04b68360fd5cddb152af6ce8927c9d25db299f98c"
+
+[[package]]
+name = "selectors"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416"
dependencies = [
- "semver-parser",
+ "bitflags",
+ "cssparser",
+ "derive_more",
+ "fxhash",
+ "log",
+ "phf 0.8.0",
+ "phf_codegen 0.8.0",
+ "precomputed-hash",
+ "servo_arc",
+ "smallvec",
]
[[package]]
@@ -1764,15 +2901,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "semver-parser"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
-dependencies = [
- "pest",
-]
-
[[package]]
name = "serde"
version = "1.0.152"
@@ -1815,6 +2943,16 @@ dependencies = [
"syn",
]
+[[package]]
+name = "servo_arc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741"
+dependencies = [
+ "nodrop",
+ "stable_deref_trait",
+]
+
[[package]]
name = "sha1"
version = "0.10.5"
@@ -1826,6 +2964,31 @@ dependencies = [
"digest",
]
+[[package]]
+name = "simba"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50582927ed6f77e4ac020c057f37a268fc6aebc29225050365aacbb9deeeddc4"
+dependencies = [
+ "approx",
+ "num-complex",
+ "num-traits",
+ "paste",
+ "wide",
+]
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14a5df39617d7c8558154693a1bb8157a4aab8179209540cc0b10e5dc24e0b18"
+
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
[[package]]
name = "skeptic"
version = "0.13.7"
@@ -1843,9 +3006,9 @@ dependencies = [
[[package]]
name = "slab"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
dependencies = [
"autocfg",
]
@@ -1858,20 +3021,67 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "socket2"
-version = "0.4.7"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc",
"winapi",
]
+[[package]]
+name = "spin"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+[[package]]
+name = "string_cache"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d69e88b23f23030bf4d0e9ca7b07434f70e1c1f4d3ca7e93ce958b373654d9f"
+dependencies = [
+ "new_debug_unreachable",
+ "once_cell",
+ "parking_lot",
+ "phf_shared 0.10.0",
+ "precomputed-hash",
+ "serde",
+]
+
+[[package]]
+name = "string_cache_codegen"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
+dependencies = [
+ "phf_generator 0.10.0",
+ "phf_shared 0.10.0",
+ "proc-macro2",
+ "quote",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
[[package]]
name = "svg_metadata"
version = "0.4.4"
@@ -1887,9 +3097,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.107"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@@ -1928,6 +3138,17 @@ dependencies = [
"windows-sys 0.42.0",
]
+[[package]]
+name = "tendril"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
+dependencies = [
+ "futf",
+ "mac",
+ "utf-8",
+]
+
[[package]]
name = "termcolor"
version = "1.2.0"
@@ -1957,6 +3178,37 @@ dependencies = [
"syn",
]
+[[package]]
+name = "threadpool"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
+dependencies = [
+ "num_cpus",
+]
+
+[[package]]
+name = "tiff"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471"
+dependencies = [
+ "flate2",
+ "jpeg-decoder",
+ "weezl",
+]
+
+[[package]]
+name = "time"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+dependencies = [
+ "libc",
+ "wasi 0.10.0+wasi-snapshot-preview1",
+ "winapi",
+]
+
[[package]]
name = "tinyvec"
version = "1.6.0"
@@ -1983,19 +3235,19 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.5.1"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
+checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
[[package]]
name = "toml_edit"
-version = "0.18.1"
+version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
+checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
dependencies = [
"indexmap",
- "nom8",
"toml_datetime",
+ "winnow",
]
[[package]]
@@ -2036,12 +3288,6 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
-[[package]]
-name = "ucd-trie"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
-
[[package]]
name = "uds_windows"
version = "1.0.2"
@@ -2069,9 +3315,9 @@ checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-ident"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "775c11906edafc97bc378816b94585fbd9a054eabaf86fdd0ced94af449efab7"
[[package]]
name = "unicode-normalization"
@@ -2082,6 +3328,12 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
[[package]]
name = "url"
version = "2.3.1"
@@ -2094,6 +3346,12 @@ dependencies = [
"serde",
]
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
[[package]]
name = "value-bag"
version = "1.0.0-alpha.9"
@@ -2133,6 +3391,18 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@@ -2215,6 +3485,12 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "weezl"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
+
[[package]]
name = "wepoll-ffi"
version = "0.1.2"
@@ -2224,6 +3500,16 @@ dependencies = [
"cc",
]
+[[package]]
+name = "wide"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b689b6c49d6549434bf944e6b0f39238cf63693cb7a147e9d887507fffa3b223"
+dependencies = [
+ "bytemuck",
+ "safe_arch",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -2336,6 +3622,26 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+[[package]]
+name = "winnow"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c95fb4ff192527911dd18eb138ac30908e7165b8944e528b6af93aa4c842d345"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "xml5ever"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4034e1d05af98b51ad7214527730626f019682d797ba38b51689212118d8e650"
+dependencies = [
+ "log",
+ "mac",
+ "markup5ever",
+]
+
[[package]]
name = "xmlparser"
version = "0.13.5"
@@ -2367,7 +3673,7 @@ dependencies = [
"nix",
"once_cell",
"ordered-stream",
- "rand",
+ "rand 0.8.5",
"serde",
"serde_repr",
"sha1",
@@ -2404,6 +3710,15 @@ dependencies = [
"zvariant",
]
+[[package]]
+name = "zune-inflate"
+version = "0.2.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589245df6230839c305984dcc0a8385cc72af1fd223f360ffd5d65efa4216d40"
+dependencies = [
+ "simd-adler32",
+]
+
[[package]]
name = "zvariant"
version = "3.11.0"
diff --git a/Cargo.toml b/Cargo.toml
index e0160a5..1f55aeb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,21 +5,32 @@ edition = "2021"
rust-version = "1.65"
license = "GPL-3.0-or-later"
+[profile.release]
+lto = true
+codegen-units = 1
+
[dependencies]
-anyhow = "1.0.66"
+anyhow = { version = "1.0.66", features = ["backtrace"] }
+arc-swap = "1.6.0"
async-global-executor = "2.3.1"
async-std = "1.12.0"
+futures = "0.3.25"
+futures-channel = "0.3.25"
gtk-macros = "0.3.0"
+indexmap = "1.9.2"
kamadak-exif = "0.5.5"
+libgweather = "4.0.0"
log = "0.4.17"
once_cell = "1.16.0"
pretty_env_logger = "0.4.0"
-futures-channel = "0.3.25"
-futures = "0.3.25"
+safe-transmute = "0.11.2"
svg_metadata = "0.4.3"
url = "2.3.1"
-libgweather = "4.0.0"
-indexmap = "1.9.2"
+
+# decoders
+image-rs = { package = "image", version = "*", git = "https://github.com/image-rs/image.git" }
+libheif-rs = "0.17.0"
+rsvg = { package = "librsvg", git = "https://gitlab.gnome.org/GNOME/librsvg.git" }
[dependencies.ashpd]
version = "0.4.0-alpha.3"
@@ -27,7 +38,7 @@ features = ["gtk4"]
[dependencies.gtk]
package = "gtk4"
-version = "0.6.0"
+version = "0.6.2"
features = ["v4_10", "xml_validation"]
[dependencies.gio]
diff --git a/README.md b/README.md
index 8528b42..dee6b0a 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,34 @@ Download bundle for:
Bundles will not be automatically updated after installation.
+## Supported Formats
+
+| Format | ICC | CICP | EXIF | XMP | Animation | Library |
+|----------|-----|------|------|-----|-----------|-------------------------------|
+| JPEG | ✔ | — | ✔ | ✘ | — | image-rs |
+| PNG | ✔ | ✘ | ✔ | ✘ | ✘ | image-rs |
+| GIF | ✘ * | — | — | ✘ | ✘ | image-rs |
+| WEBP | — | — | ✔ | ✘ | ✘ | image-rs |
+| AVIF | ✔ | ✔ | ✔ | ✘ | ✘ | libheif-rs + libheif (C++) |
+| HEIC | ✔ | ✔ | ✔ | ✘ | ✘ | libheif-rs + libheif (C++) ** |
+| TIFF | ✘ | — | ✔ | ✘ | — | image-rs |
+| SVG | ✘ | — | — | ✘ * | — | librsvg |
+| BMP | ✘ | — | — | — | — | image-rs |
+| ICO | — | — | — | — | — | image-rs |
+| PNM | — | — | — | — | — | image-rs |
+| DDS | — | — | — | — | — | image-rs |
+| TGA | — | — | — | — | — | image-rs |
+| OpenEXR | — | — | — | — | — | image-rs |
+| farbfeld | — | — | — | — | — | image-rs |
+
+| Symbol | Meaning |
+|--------|------------------------------------------------|
+| * | Unclear if used in practice, needs research |
+| ** | Split into plugin because of licensing issues |
+| ✘ | Supported by format but not implemented yet |
+| ? | Unclear if supported by format, needs research |
+| ✔ | Supported |
+
## Building
### GNOME Builder
diff --git a/build-aux/flatpak/org.gnome.Loupe.Devel.json b/build-aux/flatpak/org.gnome.Loupe.Devel.json
index a00c3d4..c986f2e 100644
--- a/build-aux/flatpak/org.gnome.Loupe.Devel.json
+++ b/build-aux/flatpak/org.gnome.Loupe.Devel.json
@@ -90,6 +90,20 @@
}
]
},
+ {
+ "name" : "libheif",
+ "buildsystem" : "cmake",
+ "config-opts": [
+
+ ],
+ "sources" : [
+ {
+ "type" : "git",
+ "url" : "https://github.com/strukturag/libheif.git",
+ "tag" : "v1.15.1"
+ }
+ ]
+ },
{
"name" : "loupe",
"buildsystem" : "meson",
diff --git a/data/gtk/image_page.ui b/data/gtk/image_page.ui
index 6ad4d93..2e73677 100644
--- a/data/gtk/image_page.ui
+++ b/data/gtk/image_page.ui
@@ -53,7 +53,7 @@
diff --git a/deny.toml b/deny.toml
index 90d78ef..5b53a88 100644
--- a/deny.toml
+++ b/deny.toml
@@ -3,10 +3,11 @@ unmaintained = "deny"
yanked = "deny"
notice = "warn"
+[advisories]
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
- #"RUSTSEC-0000-0000",
+ "RUSTSEC-2020-0071",
]
# This section is considered when running `cargo deny check licenses`
diff --git a/meson.build b/meson.build
index 319dcd4..441d6bc 100644
--- a/meson.build
+++ b/meson.build
@@ -8,8 +8,10 @@ project('loupe', 'rust',
i18n = import('i18n')
gnome = import('gnome')
-dependency('gtk4', version: '>=4.8.0')
-dependency('libadwaita-1', version: '>=1.2.0')
+dependency('gtk4', version: '>=4.9.4')
+dependency('libadwaita-1', version: '>=1.2.99')
+dependency('gweather4', version: '>=4.0.0')
+dependency('libheif', version: '>=1.14.2')
cargo = find_program('cargo', required: true)
diff --git a/src/decoder/formats/heif.rs b/src/decoder/formats/heif.rs
new file mode 100644
index 0000000..7cb692d
--- /dev/null
+++ b/src/decoder/formats/heif.rs
@@ -0,0 +1,148 @@
+///! Decode using libheif-rs
+use super::*;
+use crate::decoder::tiling::{self, TilingStoreExt};
+use crate::deps::*;
+use crate::i18n::*;
+use gtk::prelude::*;
+
+use anyhow::Context;
+use arc_swap::ArcSwap;
+use libheif_rs::{ColorSpace, HeifContext, Plane, RgbChroma};
+
+use std::path::PathBuf;
+use std::sync::Arc;
+
+#[derive(Debug)]
+pub struct Heif;
+
+impl Heif {
+ pub fn new(
+ path: PathBuf,
+ updater: UpdateSender,
+ tiles: Arc>,
+ ) -> Self {
+ log::debug!("Loading HEIF");
+ updater.spawn_error_handled(move || {
+ let ctx = HeifContext::read_from_file(&path.display().to_string())
+ .context(i18n("Failed to read image"))?;
+ let handle = ctx.primary_image_handle()?;
+
+ tiles.set_original_dimensions((handle.width(), handle.height()));
+
+ let rgb_chroma = if handle.luma_bits_per_pixel() > 8 {
+ if handle.has_alpha_channel() {
+ #[cfg(target_endian = "little")]
+ {
+ RgbChroma::HdrRgbaLe
+ }
+ #[cfg(target_endian = "big")]
+ {
+ RgbChroma::HdrRgbaBe
+ }
+ } else {
+ #[cfg(target_endian = "little")]
+ {
+ RgbChroma::HdrRgbLe
+ }
+ #[cfg(target_endian = "big")]
+ {
+ RgbChroma::HdrRgbBe
+ }
+ }
+ } else if handle.has_alpha_channel() {
+ RgbChroma::Rgba
+ } else {
+ RgbChroma::Rgb
+ };
+
+ let mut image = handle
+ .decode(ColorSpace::Rgb(rgb_chroma), None)
+ .context(i18n("Failed to decode image"))?;
+
+ let plane = image
+ .planes_mut()
+ .interleaved
+ .context("Interleaved plane does not exist")?;
+
+ let decoded = Decoded {
+ plane,
+ has_alpha_channel: handle.has_alpha_channel(),
+ pre_multiplied_alpha: handle.is_premultiplied_alpha(),
+ rgb_chroma,
+ };
+
+ let tile = tiling::Tile {
+ position: (0, 0),
+ zoom_level: tiling::zoom_to_level(1.),
+ bleed: 0,
+ texture: decoded.into_texture(),
+ };
+
+ tiles.push(tile);
+
+ Ok(())
+ });
+
+ Heif
+ }
+}
+
+pub struct Decoded<'a> {
+ plane: Plane<&'a mut [u8]>,
+ has_alpha_channel: bool,
+ pre_multiplied_alpha: bool,
+ rgb_chroma: RgbChroma,
+}
+
+impl<'a> Decoded<'a> {
+ pub fn into_texture(self) -> gdk::Texture {
+ let memory_format = match self.rgb_chroma {
+ RgbChroma::HdrRgbBe
+ | RgbChroma::HdrRgbaBe
+ | RgbChroma::HdrRgbLe
+ | RgbChroma::HdrRgbaLe => {
+ let transmuted: &mut [u16] =
+ safe_transmute::transmute_many_pedantic_mut(self.plane.data).unwrap();
+
+ // Scale HDR pixels to 16bit (they are usually 10bit or 12bit)
+ for pixel in transmuted.iter_mut() {
+ *pixel <<= 16 - self.plane.bits_per_pixel;
+ }
+
+ if self.has_alpha_channel {
+ if self.pre_multiplied_alpha {
+ gdk::MemoryFormat::R16g16b16a16Premultiplied
+ } else {
+ gdk::MemoryFormat::R16g16b16a16
+ }
+ } else {
+ gdk::MemoryFormat::R16g16b16
+ }
+ }
+ RgbChroma::Rgb | RgbChroma::Rgba => {
+ if self.has_alpha_channel {
+ if self.pre_multiplied_alpha {
+ gdk::MemoryFormat::R8g8b8a8Premultiplied
+ } else {
+ gdk::MemoryFormat::R8g8b8a8
+ }
+ } else {
+ gdk::MemoryFormat::R8g8b8
+ }
+ }
+ RgbChroma::C444 => unreachable!(),
+ };
+
+ let bytes = glib::Bytes::from_owned(self.plane.data.to_vec());
+
+ let tex = gdk::MemoryTexture::new(
+ self.plane.width as i32,
+ self.plane.height as i32,
+ memory_format,
+ &bytes,
+ self.plane.stride,
+ );
+
+ tex.upcast()
+ }
+}
diff --git a/src/decoder/formats/image_rs_other.rs b/src/decoder/formats/image_rs_other.rs
new file mode 100644
index 0000000..7c4bcf8
--- /dev/null
+++ b/src/decoder/formats/image_rs_other.rs
@@ -0,0 +1,156 @@
+///! Decode using image-rs
+use super::*;
+use crate::decoder::tiling::{self, TilingStoreExt};
+use crate::deps::*;
+
+use anyhow::Context;
+use arc_swap::ArcSwap;
+use gtk::prelude::*;
+
+use std::path::PathBuf;
+use std::sync::Arc;
+
+#[derive(Debug)]
+pub struct ImageRsOther;
+
+impl ImageRsOther {
+ pub fn new(
+ path: PathBuf,
+ updater: UpdateSender,
+ tiles: Arc>,
+ ) -> Self {
+ updater.spawn_error_handled(move || {
+ let dimensions = image_rs::image_dimensions(&path).context("Failed to read image")?;
+
+ tiles.set_original_dimensions(dimensions);
+
+ let mut reader = image_rs::io::Reader::open(&path).context("Failed to open image")?;
+
+ // TODO: Set something huge?
+ reader.limits(image_rs::io::Limits::no_limits());
+
+ let reader = reader
+ .with_guessed_format()
+ .context("Failed to open image")?;
+ let dynamic_image = reader.decode().context("Failed to decode image")?;
+
+ let decoded_image = Decoded { dynamic_image };
+
+ let tile = tiling::Tile {
+ position: (0, 0),
+ zoom_level: tiling::zoom_to_level(1.),
+ bleed: 0,
+ texture: decoded_image.into_texture(),
+ };
+
+ tiles.push(tile);
+
+ Ok(())
+ });
+
+ ImageRsOther
+ }
+}
+
+pub struct Decoded {
+ dynamic_image: image_rs::DynamicImage,
+}
+
+impl Decoded {
+ pub fn into_texture(self) -> gdk::Texture {
+ let (n_bytes, memory_format, layout, data) = match self.dynamic_image {
+ img @ image_rs::DynamicImage::ImageLuma8(_) => {
+ let buffer = img.to_rgb8();
+ (
+ 1,
+ gdk::MemoryFormat::R8g8b8,
+ buffer.sample_layout(),
+ buffer.into_raw(),
+ )
+ }
+ img @ image_rs::DynamicImage::ImageLumaA8(_) => {
+ let buffer = img.to_rgba8();
+ (
+ 1,
+ gdk::MemoryFormat::R8g8b8a8,
+ buffer.sample_layout(),
+ buffer.into_raw(),
+ )
+ }
+ image_rs::DynamicImage::ImageRgb8(buffer) => (
+ 1,
+ gdk::MemoryFormat::R8g8b8,
+ buffer.sample_layout(),
+ buffer.into_raw(),
+ ),
+ image_rs::DynamicImage::ImageRgba8(buffer) => (
+ 1,
+ gdk::MemoryFormat::R8g8b8a8,
+ buffer.sample_layout(),
+ buffer.into_raw(),
+ ),
+ img @ image_rs::DynamicImage::ImageLuma16(_) => {
+ let buffer = img.to_rgb16();
+ (
+ 2,
+ gdk::MemoryFormat::R16g16b16,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ )
+ }
+ img @ image_rs::DynamicImage::ImageLumaA16(_) => {
+ let buffer = img.to_rgba16();
+ (
+ 2,
+ gdk::MemoryFormat::R16g16b16a16,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ )
+ }
+ image_rs::DynamicImage::ImageRgb16(buffer) => (
+ 2,
+ gdk::MemoryFormat::R16g16b16,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ ),
+ image_rs::DynamicImage::ImageRgba16(buffer) => (
+ 2,
+ gdk::MemoryFormat::R16g16b16a16,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ ),
+ image_rs::DynamicImage::ImageRgb32F(buffer) => (
+ 4,
+ gdk::MemoryFormat::R32g32b32Float,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ ),
+ image_rs::DynamicImage::ImageRgba32F(buffer) => (
+ 4,
+ gdk::MemoryFormat::R32g32b32a32Float,
+ buffer.sample_layout(),
+ image_rs::DynamicImage::from(buffer).into_bytes(),
+ ),
+ img => {
+ let buffer = img.to_rgba16();
+ (
+ 2,
+ gdk::MemoryFormat::R16g16b16a16,
+ buffer.sample_layout(),
+ safe_transmute::transmute_vec(buffer.into_raw()).unwrap(),
+ )
+ }
+ };
+
+ let bytes = glib::Bytes::from_owned(data);
+
+ gdk::MemoryTexture::new(
+ layout.width as i32,
+ layout.height as i32,
+ memory_format,
+ &bytes,
+ layout.height_stride * n_bytes,
+ )
+ .upcast()
+ }
+}
diff --git a/src/decoder/formats/mod.rs b/src/decoder/formats/mod.rs
new file mode 100644
index 0000000..496600a
--- /dev/null
+++ b/src/decoder/formats/mod.rs
@@ -0,0 +1,9 @@
+mod heif;
+mod image_rs_other;
+mod svg;
+
+pub use heif::Heif;
+pub use image_rs_other::ImageRsOther;
+pub use svg::Svg;
+
+use super::{Decoder, UpdateSender};
diff --git a/src/decoder/formats/svg.rs b/src/decoder/formats/svg.rs
new file mode 100644
index 0000000..54f6a22
--- /dev/null
+++ b/src/decoder/formats/svg.rs
@@ -0,0 +1,219 @@
+///! Decode using librsvg
+use super::*;
+use crate::decoder::tiling::{self, TilingStoreExt};
+use crate::decoder::TileRequest;
+use crate::deps::*;
+
+use anyhow::Context;
+use arc_swap::ArcSwap;
+use gtk::prelude::*;
+
+use std::path::PathBuf;
+use std::sync::Arc;
+
+#[derive(Debug)]
+pub struct Svg {
+ thread_handle: std::thread::JoinHandle<()>,
+ current_request: Arc>,
+}
+
+#[derive(Default, Debug, Clone)]
+enum Request {
+ #[default]
+ None,
+ Exit,
+ Tile(TileRequest),
+}
+
+impl Request {
+ fn is_waiting(&self) -> bool {
+ !matches!(self, Self::None)
+ }
+}
+
+impl Drop for Svg {
+ fn drop(&mut self) {
+ let mut request = self.current_request.write().unwrap();
+ *request = Request::Exit;
+ self.thread_handle.thread().unpark();
+ }
+}
+
+impl Svg {
+ pub fn new(
+ path: PathBuf,
+ updater: UpdateSender,
+ tiles: Arc>,
+ ) -> Self {
+ let current_request: Arc> = Default::default();
+ let request_store = current_request.clone();
+
+ let thread_handle = updater.spawn_error_handled(move || {
+ let handle = rsvg::Loader::new().read_path(path)?;
+ let renderer = rsvg::CairoRenderer::new(&handle);
+
+ let (original_width, original_height) = svg_dimensions(&renderer);
+
+ tiles.set_original_dimensions((original_width, original_height));
+
+ loop {
+ let tile_request = {
+ let mut request = request_store.write().unwrap();
+ let value = request.clone();
+ *request = Request::None;
+ value
+ };
+
+ match tile_request {
+ Request::None => {
+ std::thread::park();
+ }
+ Request::Exit => {
+ log::debug!("Terminating decoder thread.");
+ break;
+ }
+ Request::Tile(tile_request) => {
+ let tiling = tiling::Tiling {
+ tile_size: tiling::TILE_SIZE,
+ original_dimensions: (original_width, original_height),
+ zoom: tile_request.zoom,
+ bleed: 2,
+ };
+
+ let relevant_tiles = tiling.relevant_tiles(&tile_request.viewport);
+
+ for tile_instructions in relevant_tiles {
+ if request_store.read().unwrap().is_waiting() {
+ break;
+ }
+
+ if tiles
+ .load()
+ .contains(tile_request.zoom, tile_instructions.coordinates)
+ {
+ continue;
+ }
+
+ let area = tile_instructions.area_with_bleed();
+ let surface = cairo::ImageSurface::create(
+ cairo::Format::ARgb32,
+ area.width() as i32,
+ area.height() as i32,
+ )?;
+
+ let context = cairo::Context::new(surface.clone())?;
+ let (total_width, total_height) =
+ tile_instructions.tiling.scaled_dimensions();
+
+ // librsvg does not currently support larger images
+ //
+ // TODO: We are only creating tiles, maybe this check in librsvg is wrong?
+ if total_height > 32_767 || total_width > 32_767 {
+ continue;
+ }
+
+ renderer
+ .render_document(
+ &context,
+ &cairo::Rectangle::new(
+ -area.x() as f64,
+ -area.y() as f64,
+ total_width as f64,
+ total_height as f64,
+ ),
+ )
+ .context("Failed to render image")?;
+ drop(context);
+
+ let decoded_image = Decoded { surface };
+
+ let tile = tiling::Tile {
+ position: (
+ tile_instructions.area.x() as u32,
+ tile_instructions.area.y() as u32,
+ ),
+ zoom_level: tiling::zoom_to_level(tile_instructions.tiling.zoom),
+ bleed: 2,
+ texture: decoded_image.into_texture(),
+ };
+
+ tiles.push(tile.clone());
+ }
+ }
+ }
+ }
+
+ Ok(())
+ });
+
+ Self {
+ thread_handle,
+ current_request,
+ }
+ }
+
+ pub fn request(&self, request: TileRequest, _abstract_decoder: &Decoder) -> anyhow::Result<()> {
+ let mut current_request = self.current_request.write().unwrap();
+ *current_request = Request::Tile(request);
+ self.thread_handle.thread().unpark();
+
+ Ok(())
+ }
+}
+
+pub fn svg_dimensions(renderer: &rsvg::CairoRenderer) -> (u32, u32) {
+ if let Some((width, height)) = renderer.intrinsic_size_in_pixels() {
+ (width.ceil() as u32, height.ceil() as u32)
+ } else {
+ match renderer.intrinsic_dimensions() {
+ rsvg::IntrinsicDimensions {
+ width:
+ rsvg::Length {
+ length: width,
+ unit: rsvg::LengthUnit::Percent,
+ },
+ height:
+ rsvg::Length {
+ length: height,
+ unit: rsvg::LengthUnit::Percent,
+ },
+ vbox: Some(vbox),
+ } => (
+ (width * vbox.width()).ceil() as u32,
+ (height * vbox.height()).ceil() as u32,
+ ),
+ dimensions => {
+ log::warn!("Failed to parse SVG dimensions: {dimensions:?}");
+ (300, 300)
+ }
+ }
+ }
+}
+
+struct Decoded {
+ surface: cairo::ImageSurface,
+}
+
+impl Decoded {
+ pub fn into_texture(self) -> gdk::Texture {
+ let memory_format = {
+ #[cfg(target_endian = "little")]
+ {
+ gdk::MemoryFormat::B8g8r8a8
+ }
+
+ #[cfg(target_endian = "big")]
+ {
+ gdk::MemoryFormat::A8r8g8b8
+ }
+ };
+
+ let width = self.surface.width();
+ let height = self.surface.height();
+ let stride = self.surface.stride() as usize;
+
+ let bytes = glib::Bytes::from_owned(self.surface.take_data().unwrap().to_vec());
+
+ gdk::MemoryTexture::new(width, height, memory_format, &bytes, stride).upcast()
+ }
+}
diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
new file mode 100644
index 0000000..b40d292
--- /dev/null
+++ b/src/decoder/mod.rs
@@ -0,0 +1,158 @@
+///! Decodes several image formats
+mod formats;
+pub mod tiling;
+
+use crate::image_metadata::ImageMetadata;
+use formats::*;
+use tiling::TilingStoreExt;
+
+use anyhow::Context;
+use arc_swap::ArcSwap;
+use futures::channel::mpsc;
+use gio::prelude::*;
+use gtk::graphene;
+
+use std::io::Read;
+use std::sync::Arc;
+
+#[derive(Clone, Copy, Debug)]
+pub enum ImageFormat {
+ ImageRs(image_rs::ImageFormat),
+ // TODO: Add details about contained format
+ Heif,
+ Svg,
+}
+
+impl std::fmt::Display for ImageFormat {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ match self {
+ Self::ImageRs(format) => write!(f, "{:?}", format),
+ Self::Heif => write!(f, "HEIF"),
+ Self::Svg => write!(f, "SVG"),
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+/// Renderer requests new tiles
+///
+/// This happens for initial loading or when zoom level or viewing area changes.
+pub struct TileRequest {
+ pub viewport: graphene::Rect,
+ pub zoom: f64,
+}
+
+#[derive(Debug, Clone)]
+/// Signals update to the renderer
+pub struct UpdateSender {
+ sender: mpsc::UnboundedSender,
+}
+
+#[derive(Debug)]
+/// Signals for renderer
+pub enum DecoderUpdate {
+ /// Dimensions of image in `TilingSore` available/updated
+ Dimensions,
+ /// Metadata available
+ Metadata(ImageMetadata),
+ /// Image format determined
+ Format(ImageFormat),
+ /// New image data available, redraw
+ Redraw,
+ /// And error occured during decoding
+ Error(anyhow::Error),
+}
+
+impl UpdateSender {
+ pub fn send(&self, update: DecoderUpdate) {
+ let result = self.sender.unbounded_send(update);
+
+ if let Err(err) = result {
+ log::error!("Failed to send update: {err}");
+ }
+ }
+
+ /// Send occuring errors to renderer
+ pub fn spawn_error_handled(&self, f: F) -> std::thread::JoinHandle<()>
+ where
+ F: FnOnce() -> Result<(), anyhow::Error> + Send + 'static,
+ {
+ let update_sender = self.clone();
+ std::thread::spawn(move || {
+ if let Err(err) = f() {
+ update_sender.send(DecoderUpdate::Error(err));
+ }
+ })
+ }
+}
+
+#[derive(Debug)]
+pub struct Decoder {
+ decoder: FormatDecoder,
+}
+
+#[derive(Debug)]
+enum FormatDecoder {
+ ImageRsOther(ImageRsOther),
+ Svg(Svg),
+ Heif(Heif),
+}
+
+impl Decoder {
+ /// Get new image decoder
+ ///
+ /// The textures will be stored in the passed `TilingStore`.
+ /// The renderer should listen to updates from the returned receiver.
+ pub fn new(
+ file: gio::File,
+ tiles: Arc>,
+ ) -> anyhow::Result<(Self, mpsc::UnboundedReceiver)> {
+ let path = file.path().context("Need a file path")?;
+ let (sender, receiver) = mpsc::unbounded();
+
+ let update_sender = UpdateSender { sender };
+ tiles.set_update_sender(update_sender.clone());
+
+ update_sender.send(DecoderUpdate::Metadata(ImageMetadata::load(&path)));
+
+ let mut buf = Vec::new();
+ let file = std::fs::File::open(&path)?;
+ file.take(64).read_to_end(&mut buf)?;
+ let format = image_rs::guess_format(&buf);
+
+ let decoder = if let Ok(format) = format {
+ match format {
+ image_rs::ImageFormat::Avif => {
+ update_sender.send(DecoderUpdate::Format(ImageFormat::Heif));
+ FormatDecoder::Heif(Heif::new(path, update_sender, tiles))
+ }
+ format => {
+ update_sender.send(DecoderUpdate::Format(ImageFormat::ImageRs(format)));
+ FormatDecoder::ImageRsOther(ImageRsOther::new(path, update_sender, tiles))
+ }
+ }
+ }
+ // TODO: Use mime glib mime type detection
+ else if [Some("svg"), Some("svgz")].contains(&path.extension().and_then(|x| x.to_str())) {
+ update_sender.send(DecoderUpdate::Format(ImageFormat::Svg));
+ FormatDecoder::Svg(Svg::new(path, update_sender, tiles))
+ } else if [Some("heic"), Some("avif")].contains(&path.extension().and_then(|x| x.to_str()))
+ {
+ update_sender.send(DecoderUpdate::Format(ImageFormat::Heif));
+ FormatDecoder::Heif(Heif::new(path, update_sender, tiles))
+ } else {
+ return None.context("unknown image format");
+ };
+
+ Ok((Self { decoder }, receiver))
+ }
+
+ /// Request missing tiles
+ pub fn request(&self, tile_request: TileRequest) {
+ match &self.decoder {
+ FormatDecoder::Svg(svg) => svg.request(tile_request, self).unwrap(),
+ FormatDecoder::Heif(_) => {}
+ _ => {}
+ };
+ }
+}
diff --git a/src/decoder/tiling.rs b/src/decoder/tiling.rs
new file mode 100644
index 0000000..6e8c47a
--- /dev/null
+++ b/src/decoder/tiling.rs
@@ -0,0 +1,483 @@
+///! Tiled renderer
+///!
+///! It is not always feasible or desiareble to store the complete decoded
+///! image in the VRAM. [`TilingStore`] allows to compose the parts of
+///! the image currently viewed, out of smaller [`Tiles`].
+///!
+///! This is especially important for SVGs where every the image has to
+///! be re-genearted for each zoom level. It can also be used to allow
+///! showing large JPEGs etc where the complete decoded image would not
+///! even fit in the VRAM.
+use super::{DecoderUpdate, UpdateSender};
+use crate::deps::*;
+
+use arc_swap::ArcSwap;
+use gtk::prelude::*;
+
+use std::collections::BTreeMap;
+use std::sync::Arc;
+
+const ZOOM_SIGNIFICANT_DIGETS: i32 = 6;
+pub const TILE_SIZE: u16 = 4000;
+
+pub type ZoomLevel = u32;
+pub type Coordinate = u32;
+pub type Coordinates = (u32, u32);
+
+#[derive(Clone, Debug)]
+/// Part of the image
+pub struct Tile {
+ pub position: Coordinates,
+ pub zoom_level: ZoomLevel,
+ /// Border that gets cut away to avoid scaling artifacts at the sides
+ pub bleed: u8,
+ pub texture: gdk::Texture,
+}
+
+impl Tile {
+ pub fn area(&self) -> graphene::Rect {
+ let bleed = self.bleed as f32;
+ // The texture is rendered slightly larger such that bleed can be cut away
+ self.area_with_bleed().inset_r(bleed, bleed)
+ }
+
+ pub fn area_with_bleed(&self) -> graphene::Rect {
+ let width = self.texture.width() as f32;
+ let height = self.texture.height() as f32;
+ let bleed = self.bleed as f32;
+ graphene::Rect::new(
+ self.position.0 as f32 - bleed,
+ self.position.1 as f32 - bleed,
+ width,
+ height,
+ )
+ }
+
+ pub fn zoom(&self) -> f32 {
+ level_to_zoom(self.zoom_level) as f32
+ }
+
+ /// Add tile to snapshot
+ ///
+ /// This is where parts of images actually land on the screen
+ pub fn add_to_snapshot(&self, snapshot: >k::Snapshot, options: &RenderOptions) {
+ let zoom = self.zoom();
+ let area = self.area().scale(1. / zoom, 1. / zoom);
+ let area_with_bleed = self.area_with_bleed().scale(1. / zoom, 1. / zoom);
+
+ // TODO: do not clip outer bounderies of the image
+ snapshot.push_clip(&area);
+ snapshot.append_color(&gdk::RGBA::new(0.118, 0.118, 0.118, 1.), &area);
+ snapshot.append_scaled_texture(&self.texture, options.scaling_filter, &area_with_bleed);
+ snapshot.pop();
+ }
+
+ fn coordinates(&self) -> Coordinates {
+ self.position
+ }
+}
+
+#[derive(Clone, Debug)]
+/// Store tiles for image
+pub struct TilingStore {
+ pub tiles: BTreeMap>,
+ /// Tile size without bleed
+ pub tile_size: u16,
+ /// Complete image size
+ pub original_dimensions: Option,
+ pub update_sender: Option,
+}
+
+impl Default for TilingStore {
+ fn default() -> Self {
+ Self::new(TILE_SIZE)
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct RenderOptions {
+ pub scaling_filter: gsk::ScalingFilter,
+}
+
+impl TilingStore {
+ pub fn new(tile_size: u16) -> Self {
+ TilingStore {
+ tiles: Default::default(),
+ tile_size,
+ original_dimensions: None,
+ update_sender: None,
+ }
+ }
+
+ /// Render tiles as image
+ ///
+ /// This is what actually draws the image
+ pub fn add_to_snapshot(&self, snapshot: >k::Snapshot, zoom: f64, options: &RenderOptions) {
+ let tiles: Vec<_> = self
+ .iter_rendering_priority(zoom)
+ .flat_map(|(_, tiles)| tiles)
+ .collect();
+
+ log::trace!("Rendering {} tiles", tiles.len());
+ // reverse to put least fitting tiles in the background
+ for (_, tile) in tiles.iter().rev() {
+ tile.add_to_snapshot(snapshot, options);
+ }
+ }
+
+ pub fn push(&mut self, tile: Tile) {
+ let map = self.tiles.entry(tile.zoom_level).or_default();
+ map.insert(tile.coordinates(), tile);
+ if let Some(updater) = &self.update_sender {
+ updater.send(DecoderUpdate::Redraw);
+ }
+ }
+
+ pub fn set_original_dimensions(&mut self, dimensions: Coordinates) {
+ self.original_dimensions = Some(dimensions);
+ if let Some(updater) = &self.update_sender {
+ updater.send(DecoderUpdate::Dimensions);
+ }
+ }
+
+ pub fn set_update_sender(&mut self, sender: UpdateSender) {
+ self.update_sender = Some(sender);
+ }
+
+ pub fn contains(&self, zoom: f64, coordinates: Coordinates) -> bool {
+ let Some(tile_plane) = self.tiles.get(&zoom_to_level(zoom)) else { return false };
+
+ tile_plane.contains_key(&coordinates)
+ }
+
+ /// Tiles ordered by how good they are suited for the zoom level
+ pub fn iter_rendering_priority(
+ &self,
+ zoom: f64,
+ ) -> impl Iterator- )> {
+ let zoom_level = zoom_to_level(zoom);
+ self.tiles
+ // Tiles at zoom level and with better resolution
+ .range(zoom_level..)
+ // Afterwards try tiles with worse resolution
+ .chain(self.tiles.range(..zoom_level).rev())
+ }
+
+ /// Viewport within zoom coordinates
+ ///
+ /// TODO: This is the most buggy function ever
+ pub fn cleanup(&mut self, zoom: f64, viewport: graphene::Rect) {
+ let Some(original_dimensions) = self.original_dimensions else { log::error!("Too-early cleanup: Original dimension not known"); return; };
+
+ let mut kept_tiles = Self::new(self.tile_size);
+
+ // Always work with 100% zoom level for tiles
+ let mut missing_tiles = vec![viewport.scale(1. / zoom as f32, 1. / zoom as f32)];
+
+ // Keep tiles in top layer
+ // TODO: Change the top layer if window size changes
+ if let Some(top_layer) = self.tiles.iter().next() {
+ for tile in top_layer.1.values() {
+ kept_tiles.push(tile.clone());
+ }
+ }
+
+ // Put all tiles in correct processing order
+ let stored_tiles = self.iter_rendering_priority(zoom);
+
+ for (zoom_level, tiles) in stored_tiles {
+ let tile_zoom = level_to_zoom(*zoom_level);
+
+ let mut next_missing_tiles = vec![];
+
+ // Tiling for this zoom level and viewport
+ let tiling = Tiling {
+ tile_size: self.tile_size,
+ original_dimensions,
+ zoom: tile_zoom,
+ bleed: 2,
+ };
+
+ for mut tile_instruction in tiling.relevant_tiles(&viewport) {
+ // scale to 100% reference
+ tile_instruction.area = tile_instruction
+ .area
+ .scale(1. / tile_zoom as f32, 1. / tile_zoom as f32);
+
+ // Determine if tile of this zoom level has overlap with a missing tile
+ let mut intersections = missing_tiles
+ .iter()
+ .filter(|missing| tile_instruction.area.is_intersected(missing))
+ .peekable();
+
+ if intersections.peek().is_some() {
+ if let Some(tile) = tiles.get(&tile_instruction.coordinates) {
+ // we have this tile and can provide it
+ kept_tiles.push(tile.clone());
+ } else {
+ for missing in missing_tiles.iter() {
+ if let Some(overlap) = missing.intersection(&tile_instruction.area) {
+ next_missing_tiles.push(overlap);
+ }
+ }
+ }
+ }
+ }
+
+ missing_tiles = next_missing_tiles;
+ }
+
+ kept_tiles.tiles.values().flat_map(|x| x.iter()).count();
+
+ self.tiles = kept_tiles.tiles;
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+/// Abstract definition of a tiling
+pub struct Tiling {
+ pub tile_size: u16,
+ pub original_dimensions: Coordinates,
+ pub zoom: f64,
+ pub bleed: u8,
+}
+
+impl Tiling {
+ pub fn scaled_dimensions(&self) -> Coordinates {
+ let (w, h) = self.original_dimensions;
+ (
+ (w as f64 * self.zoom) as Coordinate,
+ (h as f64 * self.zoom) as Coordinate,
+ )
+ }
+
+ /// Returns relevant tiles
+ ///
+ /// This gives what tiles are needed for convering the `preload_area`.
+ /// Decoders use the [`TileInstructions`] to know what they have to render.
+ pub fn relevant_tiles(&self, preload_area: &graphene::Rect) -> Vec {
+ let tile_size = self.tile_size as f32;
+
+ let x0 = (preload_area.x() / tile_size).floor() * tile_size;
+ let x1 = ((preload_area.x() + preload_area.width()) / tile_size).ceil() * tile_size;
+ let y0 = (preload_area.y() / tile_size).floor() * tile_size;
+ let y1 = ((preload_area.y() + preload_area.height()) / tile_size).ceil() * tile_size;
+
+ let mut tiles = Vec::new();
+ for x in (x0 as u32..x1 as u32).step_by(self.tile_size.into()) {
+ for y in (y0 as u32..y1 as u32).step_by(self.tile_size.into()) {
+ let width = tile_size
+ + f32::min(
+ 0.,
+ self.scaled_dimensions().0 as f32 - (x as f32 + tile_size),
+ );
+ let height = tile_size
+ + f32::min(
+ 0.,
+ self.scaled_dimensions().1 as f32 - (y as f32 + tile_size),
+ );
+
+ let area = graphene::Rect::new(x as f32, y as f32, width, height);
+ let tile = TileInstructions {
+ tiling: *self,
+ area,
+ coordinates: (x, y),
+ };
+ tiles.push(tile);
+ }
+ }
+
+ tiles.sort_by_key(|tile| tile.area.center().distance(&preload_area.center()).0 as u32);
+
+ tiles
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+/// Instruction for decoder to generate this tile
+pub struct TileInstructions {
+ pub tiling: Tiling,
+ pub area: graphene::Rect,
+ pub coordinates: Coordinates,
+}
+
+impl TileInstructions {
+ pub fn area_with_bleed(&self) -> graphene::Rect {
+ let bleed = self.tiling.bleed as f32;
+ self.area.inset_r(-bleed, -bleed)
+ }
+}
+
+/// Integer zoom levels are used because they are hashable
+/// and ignore tiny float calculation errors.
+pub fn zoom_to_level(zoom: f64) -> u32 {
+ (zoom * 10_f64.powi(ZOOM_SIGNIFICANT_DIGETS)) as u32
+}
+
+pub fn level_to_zoom(zoom_level: u32) -> f64 {
+ zoom_level as f64 * 10_f64.powi(-ZOOM_SIGNIFICANT_DIGETS)
+}
+
+pub fn zoom_normalize(zoom: f64) -> f64 {
+ level_to_zoom(zoom_to_level(zoom))
+}
+
+trait RectExt {
+ fn is_intersected(&self, b: &graphene::Rect) -> bool;
+}
+
+impl RectExt for graphene::Rect {
+ fn is_intersected(&self, b: &graphene::Rect) -> bool {
+ self.intersection(b).is_some()
+ }
+}
+
+pub trait TilingStoreExt {
+ fn push(&self, tile: Tile);
+ fn set_original_dimensions(&self, size: Coordinates);
+ fn set_update_sender(&self, sender: UpdateSender);
+}
+
+impl TilingStoreExt for ArcSwap {
+ fn push(&self, tile: Tile) {
+ self.rcu(|tiling_store| {
+ let mut new_store = (**tiling_store).clone();
+ new_store.push(tile.clone());
+ Arc::new(new_store)
+ });
+ }
+
+ fn set_original_dimensions(&self, size: Coordinates) {
+ self.rcu(|tiling_store| {
+ let mut new_store = (**tiling_store).clone();
+ new_store.set_original_dimensions(size);
+ Arc::new(new_store)
+ });
+ }
+
+ fn set_update_sender(&self, sender: UpdateSender) {
+ self.rcu(|tiling_store| {
+ let mut new_store = (**tiling_store).clone();
+ new_store.set_update_sender(sender.clone());
+ Arc::new(new_store)
+ });
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_tiling_cleanup() {
+ let mut store = TilingStore::new(2);
+
+ let toplevel = Tile {
+ position: (0, 0),
+ zoom_level: zoom_to_level(1.),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 4,
+ 4,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 4 * 4 * 3]),
+ 4 * 3,
+ )
+ .upcast(),
+ };
+ store.push(toplevel);
+
+ let right_level = Tile {
+ position: (0, 0),
+ zoom_level: zoom_to_level(1.5),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 2,
+ 2,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 2 * 2 * 3]),
+ 2 * 3,
+ )
+ .upcast(),
+ };
+ store.push(right_level);
+
+ let low_level = Tile {
+ position: (2, 0),
+ zoom_level: zoom_to_level(1.6),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 2,
+ 2,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 2 * 2 * 3]),
+ 2 * 3,
+ )
+ .upcast(),
+ };
+ store.push(low_level);
+
+ let overlapped = Tile {
+ position: (0, 0),
+ zoom_level: zoom_to_level(1.7),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 2,
+ 2,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 2 * 2 * 3]),
+ 2 * 3,
+ )
+ .upcast(),
+ };
+ store.push(overlapped);
+
+ store.cleanup(1.5, graphene::Rect::new(0., 0., 4. * 1.5, 4. * 1.5));
+
+ assert!(store.tiles.get(&1000000).unwrap().get(&(0, 0)).is_some());
+ assert!(store.tiles.get(&1500000).unwrap().get(&(0, 0)).is_some());
+ assert!(store.tiles.get(&1600000).unwrap().get(&(2, 0)).is_some());
+ // TODO: This should pass, but it does not
+ //assert!(store.tiles.get(&1700000).is_none());
+ }
+
+ #[test]
+ fn test_tiling_cleanup_simple() {
+ let mut store = TilingStore::new(2);
+
+ let toplevel = Tile {
+ position: (0, 0),
+ zoom_level: zoom_to_level(1.),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 4,
+ 4,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 4 * 4 * 3]),
+ 4 * 3,
+ )
+ .upcast(),
+ };
+ store.push(toplevel);
+
+ let detailled = Tile {
+ position: (2, 2),
+ zoom_level: zoom_to_level(2.),
+ bleed: 0,
+ texture: gdk::MemoryTexture::new(
+ 4,
+ 4,
+ gdk::MemoryFormat::R8g8b8,
+ &glib::Bytes::from_static(&[0; 4 * 4 * 3]),
+ 4 * 3,
+ )
+ .upcast(),
+ };
+ store.push(detailled);
+
+ store.cleanup(1.5, graphene::Rect::new(0., 0., 20., 20.));
+
+ assert!(store.tiles.get(&1000000).unwrap().get(&(0, 0)).is_some());
+ assert!(store.tiles.get(&2000000).unwrap().get(&(2, 2)).is_some());
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index f7c39be..3fb7ab7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -22,6 +22,7 @@ use gtk::gio::{self, prelude::*};
mod application;
mod config;
+mod decoder;
mod file_model;
mod i18n;
mod image_metadata;
@@ -31,7 +32,7 @@ mod widgets;
mod window;
mod deps {
- pub use gtk::{gdk, gdk_pixbuf, gio, glib, graphene, gsk};
+ pub use gtk::{cairo, gdk, gdk_pixbuf, gio, glib, graphene, gsk};
}
use application::LpApplication;
diff --git a/src/meson.build b/src/meson.build
index d41fced..33b1f5d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -67,4 +67,17 @@ cargo_doc = custom_target(
cargo, 'doc',
cargo_options + ['--no-deps', '--document-private-items'],
],
-)
\ No newline at end of file
+)
+
+test(
+ 'cargo-test',
+ cargo,
+ args: [
+ 'test',
+ cargo_options,
+ '--',
+ '--test-threads=1',
+ ],
+ is_parallel: false,
+ timeout: 1800,
+)
diff --git a/src/widgets/image.rs b/src/widgets/image.rs
index 0d45992..2243860 100644
--- a/src/widgets/image.rs
+++ b/src/widgets/image.rs
@@ -17,18 +17,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::deps::*;
+
+use crate::decoder::{self, tiling, Decoder, DecoderUpdate};
use crate::i18n::i18n;
-use crate::image_metadata::{ImageMetadata, LpImageMetadata};
+use crate::image_metadata::LpImageMetadata;
use crate::util;
use adw::{prelude::*, subclass::prelude::*};
-use anyhow::Context;
+use arc_swap::ArcSwap;
+use futures::prelude::*;
use gtk_macros::spawn;
use once_cell::sync::Lazy;
use once_cell::unsync::OnceCell;
use std::cell::{Cell, RefCell};
use std::path::{Path, PathBuf};
+use std::sync::Arc;
/// Milliseconds
const ZOOM_ANIMATION_DURATION: u32 = 200;
@@ -65,9 +69,13 @@ mod imp {
pub is_deleted: Cell,
/// Track changes to this image
pub file_monitor: RefCell