feat(imaging): add pure-Rust Skia backend (#112)
This commit is contained in:
@@ -16,6 +16,35 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
rust-skia:
|
||||||
|
name: rust-skia (Rust only)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
env:
|
||||||
|
CARGO_BUILD_JOBS: "1"
|
||||||
|
CARGO_INCREMENTAL: "0"
|
||||||
|
CARGO_PROFILE_DEV_DEBUG: "0"
|
||||||
|
CARGO_PROFILE_TEST_DEBUG: "0"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Deliberately do not install CMake, Clang, pkg-config, Skia, WebP, or
|
||||||
|
# any other native codec prerequisite in this job.
|
||||||
|
- name: Install pinned Rust
|
||||||
|
uses: dtolnay/rust-toolchain@master
|
||||||
|
with:
|
||||||
|
toolchain: 1.97.1
|
||||||
|
targets: wasm32-unknown-unknown
|
||||||
|
|
||||||
|
- name: Test the pure-Rust Skia-compatible extension
|
||||||
|
run: cargo test --locked -j 1 -p libremetaverse-imaging-skia --no-default-features --features rust-skia
|
||||||
|
|
||||||
|
- name: Audit the normal and build dependency graph
|
||||||
|
run: cargo tree --locked -p libremetaverse-imaging-skia --no-default-features --features rust-skia -e normal,build
|
||||||
|
|
||||||
|
- name: Compile the same Rust codec for WASM
|
||||||
|
run: cargo check --locked -j 1 -p libremetaverse-imaging-skia --no-default-features --features rust-skia --target wasm32-unknown-unknown
|
||||||
|
|
||||||
required:
|
required:
|
||||||
name: required
|
name: required
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
569
Cargo.lock
generated
569
Cargo.lock
generated
@@ -52,6 +52,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alsa"
|
name = "alsa"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@@ -59,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d"
|
checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alsa-sys",
|
"alsa-sys",
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -143,6 +149,15 @@ dependencies = [
|
|||||||
"ogg_next_sys",
|
"ogg_next_sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.8"
|
version = "0.7.8"
|
||||||
@@ -254,7 +269,7 @@ version = "0.72.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"cexpr",
|
"cexpr",
|
||||||
"clang-sys",
|
"clang-sys",
|
||||||
"itertools",
|
"itertools",
|
||||||
@@ -263,11 +278,26 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash 2.1.3",
|
||||||
"shlex 1.3.0",
|
"shlex 1.3.0",
|
||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-set"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
||||||
|
dependencies = [
|
||||||
|
"bit-vec 0.8.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit-vec"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-vec"
|
name = "bit-vec"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
@@ -277,6 +307,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.13.1"
|
version = "2.13.1"
|
||||||
@@ -316,6 +352,38 @@ version = "3.20.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.25.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck_derive"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc0e56a716f1e132ff6bf4bdac1c944a3fcdc1cae65f70a4a2a1ac3b401d2d1f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder-lite"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.12.1"
|
version = "1.12.1"
|
||||||
@@ -479,6 +547,22 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@@ -529,7 +613,7 @@ version = "0.14.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58"
|
checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2-audio-toolbox",
|
"objc2-audio-toolbox",
|
||||||
"objc2-core-audio",
|
"objc2-core-audio",
|
||||||
@@ -823,7 +907,7 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -844,6 +928,15 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "earcut"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88459a2a8e3a514b6e6de38cf3aaa9250a894cb098f74a932db77fcc8341b6d0"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ecdsa"
|
name = "ecdsa"
|
||||||
version = "0.16.9"
|
version = "0.16.9"
|
||||||
@@ -907,6 +1000,15 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fearless_simd"
|
name = "fearless_simd"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -961,6 +1063,18 @@ dependencies = [
|
|||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float_next_after"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37007738a80ea34f969af54a3390dd72cacdef654974cfd449c9f6f72dbaac10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@@ -1047,6 +1161,51 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo"
|
||||||
|
version = "0.33.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30eb1fdc57c1e5cfd11826fe0caec4b9dc7901f3758263bb506228d88c8d9e9a"
|
||||||
|
dependencies = [
|
||||||
|
"earcut",
|
||||||
|
"float_next_after",
|
||||||
|
"geo-types",
|
||||||
|
"geographiclib-rs",
|
||||||
|
"i_overlay",
|
||||||
|
"log",
|
||||||
|
"num-traits",
|
||||||
|
"rand 0.10.2",
|
||||||
|
"rand_pcg",
|
||||||
|
"robust",
|
||||||
|
"rstar",
|
||||||
|
"sif-itree",
|
||||||
|
"spade",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo-types"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "777d18aa0f12f8b285331cd867133ee14422b3f023f6d388034c47d43e28786a"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-traits",
|
||||||
|
"rayon",
|
||||||
|
"rstar",
|
||||||
|
"serde",
|
||||||
|
"spade",
|
||||||
|
"thiserror 2.0.20",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geographiclib-rs"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5a7f08910fd98737a6eda7568e7c5e645093e073328eeef49758cfe8b0489c7"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@@ -1096,6 +1255,22 @@ dependencies = [
|
|||||||
"polyval",
|
"polyval",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.29.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
@@ -1124,18 +1299,54 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
dependencies = [
|
||||||
|
"allocator-api2",
|
||||||
|
"equivalent",
|
||||||
|
"foldhash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
|
dependencies = [
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hexf-parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
@@ -1266,6 +1477,52 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i_float"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "813145bb0ad5b60f55cbbf3c74cdceda1c0a9d253b35c4cc36ae0df7887cb78f"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i_key_sort"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d73d122b937fca067feb0ad74f62388920272b27c356d4df2d0cfdd59e044cf0"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i_overlay"
|
||||||
|
version = "4.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8dd314b4668e2b3a12508f2e125558c82a6c0a8636fa5107a900f79ce414e450"
|
||||||
|
dependencies = [
|
||||||
|
"i_float",
|
||||||
|
"i_key_sort",
|
||||||
|
"i_shape",
|
||||||
|
"i_tree",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i_shape"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa9eac533d7509a8ab87672b60ac610c17240f9ea4851d26227689fdfe349c8"
|
||||||
|
dependencies = [
|
||||||
|
"i_float",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "i_tree"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4804bdc1dc124eb7e1aa9e144ecc04096bcf787a10a15fa44af682b51f0f6cce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@@ -1369,6 +1626,16 @@ dependencies = [
|
|||||||
"icu_properties",
|
"icu_properties",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image-webp"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder-lite",
|
||||||
|
"quick-error",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.14.0"
|
version = "2.14.0"
|
||||||
@@ -1376,7 +1643,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown 0.17.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1551,6 +1818,21 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-encoder"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b454d911ac55068f53495488d8ccd0646eaa540c033a28ee15b07838afafb01f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.104"
|
version = "0.3.104"
|
||||||
@@ -1660,8 +1942,10 @@ dependencies = [
|
|||||||
name = "libremetaverse-imaging-skia"
|
name = "libremetaverse-imaging-skia"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"image-webp",
|
||||||
"libremetaverse-imaging",
|
"libremetaverse-imaging",
|
||||||
"libremetaverse-types",
|
"libremetaverse-types",
|
||||||
|
"skia-rs-codec",
|
||||||
"skia-safe",
|
"skia-safe",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1821,6 +2105,15 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.33"
|
version = "0.4.33"
|
||||||
@@ -1954,13 +2247,34 @@ dependencies = [
|
|||||||
"pxfm",
|
"pxfm",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "naga"
|
||||||
|
version = "23.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bit-set",
|
||||||
|
"bitflags 2.13.1",
|
||||||
|
"cfg_aliases 0.1.1",
|
||||||
|
"codespan-reporting",
|
||||||
|
"hexf-parse",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"rustc-hash 1.1.0",
|
||||||
|
"spirv",
|
||||||
|
"termcolor",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
|
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"jni-sys 0.3.1",
|
"jni-sys 0.3.1",
|
||||||
"log",
|
"log",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
@@ -1989,7 +2303,7 @@ version = "0.28.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases 0.1.1",
|
"cfg_aliases 0.1.1",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2002,7 +2316,7 @@ version = "0.31.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases 0.2.2",
|
"cfg_aliases 0.2.2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2070,6 +2384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"libm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2109,7 +2424,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08"
|
checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-core-audio",
|
"objc2-core-audio",
|
||||||
@@ -2124,7 +2439,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be"
|
checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
]
|
]
|
||||||
@@ -2135,7 +2450,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
]
|
]
|
||||||
@@ -2159,7 +2474,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c"
|
checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2179,7 +2494,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"block2",
|
"block2",
|
||||||
"dispatch2",
|
"dispatch2",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2192,7 +2507,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"dispatch2",
|
"dispatch2",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
@@ -2225,7 +2540,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-core-graphics",
|
"objc2-core-graphics",
|
||||||
@@ -2243,7 +2558,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"block2",
|
"block2",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2",
|
"objc2",
|
||||||
@@ -2256,7 +2571,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
@@ -2267,7 +2582,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-foundation",
|
"objc2-foundation",
|
||||||
@@ -2279,7 +2594,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2",
|
||||||
"objc2-cloud-kit",
|
"objc2-cloud-kit",
|
||||||
@@ -2385,6 +2700,29 @@ dependencies = [
|
|||||||
"sha2 0.10.9",
|
"sha2 0.10.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -2428,6 +2766,19 @@ version = "0.2.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poly1305"
|
name = "poly1305"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -2518,6 +2869,12 @@ version = "0.1.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn"
|
name = "quinn"
|
||||||
version = "0.11.11"
|
version = "0.11.11"
|
||||||
@@ -2529,7 +2886,7 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn-proto",
|
"quinn-proto",
|
||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
"rustc-hash",
|
"rustc-hash 2.1.3",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
@@ -2551,7 +2908,7 @@ dependencies = [
|
|||||||
"rand 0.10.2",
|
"rand 0.10.2",
|
||||||
"rand_pcg",
|
"rand_pcg",
|
||||||
"ring",
|
"ring",
|
||||||
"rustc-hash",
|
"rustc-hash 2.1.3",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"slab",
|
"slab",
|
||||||
@@ -2693,6 +3050,15 @@ dependencies = [
|
|||||||
"yasna",
|
"yasna",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.13.1"
|
version = "1.13.1"
|
||||||
@@ -2784,6 +3150,12 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "robust"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxmltree"
|
name = "roxmltree"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
@@ -2793,6 +3165,23 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstar"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb"
|
||||||
|
dependencies = [
|
||||||
|
"heapless",
|
||||||
|
"num-traits",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "2.1.3"
|
version = "2.1.3"
|
||||||
@@ -2823,7 +3212,7 @@ version = "1.1.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@@ -2929,6 +3318,12 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scroll"
|
name = "scroll"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@@ -2959,7 +3354,7 @@ dependencies = [
|
|||||||
"crc",
|
"crc",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.9.5",
|
"rand 0.9.5",
|
||||||
"rustc-hash",
|
"rustc-hash 2.1.3",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
]
|
]
|
||||||
@@ -2984,7 +3379,7 @@ version = "3.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -3104,6 +3499,12 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sif-itree"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7f45b8998ced5134fb1d75732c77842a3e888f19c1ff98481822e8fbfbf930b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.8"
|
version = "1.4.8"
|
||||||
@@ -3163,6 +3564,60 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skia-rs-codec"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "733be303d09c7e2bd0628dc1e592855d80e79a32c7f020f980ab0abe710d77a6"
|
||||||
|
dependencies = [
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"jpeg-encoder",
|
||||||
|
"parking_lot",
|
||||||
|
"png",
|
||||||
|
"skia-rs-core",
|
||||||
|
"skia-rs-paint",
|
||||||
|
"thiserror 2.0.20",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skia-rs-core"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88c10ce81ab452a6fa88e7228a5af713328e698b7100c2d021f58287a5370c49"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.1",
|
||||||
|
"bytemuck",
|
||||||
|
"getrandom 0.2.17",
|
||||||
|
"glam",
|
||||||
|
"smallvec",
|
||||||
|
"thiserror 2.0.20",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skia-rs-paint"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4b7ea0fc7fa887d5875e49809eabc3cbd9e6a0247930a9f6456ad4c59cedfb1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.1",
|
||||||
|
"naga",
|
||||||
|
"skia-rs-core",
|
||||||
|
"skia-rs-path",
|
||||||
|
"thiserror 2.0.20",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "skia-rs-path"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f928ca29bc3e26f46393048186bf64cf7eb7c39cc7176e8285a1828c601d7c0"
|
||||||
|
dependencies = [
|
||||||
|
"geo",
|
||||||
|
"skia-rs-core",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "skia-safe"
|
name = "skia-safe"
|
||||||
version = "0.99.0"
|
version = "0.99.0"
|
||||||
@@ -3170,7 +3625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9f512ac418a64194842dd05566320805dad1c957c521039db2486fd6368865bc"
|
checksum = "9f512ac418a64194842dd05566320805dad1c957c521039db2486fd6368865bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"skia-bindings",
|
"skia-bindings",
|
||||||
"skia-svg-macros",
|
"skia-svg-macros",
|
||||||
@@ -3209,6 +3664,27 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spade"
|
||||||
|
version = "2.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9699399fd9349b00b184f5635b074f9ec93afffef30c853f8c875b32c0f8c7fa"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown 0.16.1",
|
||||||
|
"num-traits",
|
||||||
|
"robust",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv"
|
||||||
|
version = "0.3.0+sdk-1.3.268.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spki"
|
name = "spki"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
@@ -3349,6 +3825,15 @@ dependencies = [
|
|||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
@@ -3566,7 +4051,7 @@ version = "0.6.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.13.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
@@ -3645,6 +4130,18 @@ version = "1.0.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "universal-hash"
|
name = "universal-hash"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -3699,9 +4196,19 @@ checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
"uuid-rng-internal",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid-rng-internal"
|
||||||
|
version = "1.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dff7387287837acf196f2596a6216f94c555d947d5331e1cc48393131020119"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
@@ -3859,6 +4366,12 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "widestring"
|
name = "widestring"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@@ -4144,7 +4657,7 @@ version = "0.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282"
|
checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-vec",
|
"bit-vec 0.9.1",
|
||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ The currently available opt-in codec backends are:
|
|||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Raw J2K and JP2 decoding/encoding through OpenJPEG | `libremetaverse/jpeg2000` | `cargo build -p libremetaverse --features jpeg2000` | OpenJPEG 2.5.4 or newer |
|
| Raw J2K and JP2 decoding/encoding through OpenJPEG | `libremetaverse/jpeg2000` | `cargo build -p libremetaverse --features jpeg2000` | OpenJPEG 2.5.4 or newer |
|
||||||
| Raw J2K and JP2 decoding/encoding in pure Rust | `libremetaverse/rust-j2k` | `cargo build -p libremetaverse --no-default-features --features rust-j2k` | none |
|
| Raw J2K and JP2 decoding/encoding in pure Rust | `libremetaverse/rust-j2k` | `cargo build -p libremetaverse --no-default-features --features rust-j2k` | none |
|
||||||
| BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP decoding through Skia | `libremetaverse-imaging-skia/skia` | `cargo build -p libremetaverse-imaging-skia --features skia` | A matching rust-skia binary cache, or the documented native source-build tools |
|
| BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP decoding in pure Rust | `libremetaverse-imaging-skia/rust-skia` | `cargo build -p libremetaverse-imaging-skia --features rust-skia` | None |
|
||||||
|
| BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP decoding through native Skia | `libremetaverse-imaging-skia/skia` | `cargo build -p libremetaverse-imaging-skia --features skia` | A matching rust-skia binary cache, or the documented native source-build tools |
|
||||||
| PCM to Ogg Vorbis encoding | `libremetaverse/vorbis` | `cargo build -p libremetaverse --features vorbis` | `vorbis_rs` 0.5.6 and its native encoder build prerequisites |
|
| PCM to Ogg Vorbis encoding | `libremetaverse/vorbis` | `cargo build -p libremetaverse --features vorbis` | `vorbis_rs` 0.5.6 and its native encoder build prerequisites |
|
||||||
|
|
||||||
Run their focused test suites with:
|
Run their focused test suites with:
|
||||||
@@ -71,6 +72,7 @@ Run their focused test suites with:
|
|||||||
cargo test -p libremetaverse-imaging --features jpeg2000
|
cargo test -p libremetaverse-imaging --features jpeg2000
|
||||||
cargo test -p libremetaverse-imaging --no-default-features --features rust-j2k
|
cargo test -p libremetaverse-imaging --no-default-features --features rust-j2k
|
||||||
cargo test -p libremetaverse-imaging-skia --features skia
|
cargo test -p libremetaverse-imaging-skia --features skia
|
||||||
|
cargo test -p libremetaverse-imaging-skia --features rust-skia
|
||||||
cargo test -p libremetaverse --no-default-features --features vorbis
|
cargo test -p libremetaverse --no-default-features --features vorbis
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ MSRV, features, and licenses at adoption time.
|
|||||||
| `System.Net.Http` / WinHTTP | [`reqwest` 0.13.4](https://crates.io/crates/reqwest/0.13.4) | MSRV 1.85. Use rustls/default TLS deliberately, connection pooling, streaming bodies, and injected client/timeouts. |
|
| `System.Net.Http` / WinHTTP | [`reqwest` 0.13.4](https://crates.io/crates/reqwest/0.13.4) | MSRV 1.85. Use rustls/default TLS deliberately, connection pooling, streaming bodies, and injected client/timeouts. |
|
||||||
| JSON and general data mapping | [`serde` 1.0.229](https://crates.io/crates/serde/1.0.229), [`serde_json` 1.0.151](https://crates.io/crates/serde_json/1.0.151), [`serde_bytes` 0.11.19](https://crates.io/crates/serde_bytes/0.11.19) | Use only where the C# implementation is schema-driven JSON. Hand-write LLSD encodings. |
|
| JSON and general data mapping | [`serde` 1.0.229](https://crates.io/crates/serde/1.0.229), [`serde_json` 1.0.151](https://crates.io/crates/serde_json/1.0.151), [`serde_bytes` 0.11.19](https://crates.io/crates/serde_bytes/0.11.19) | Use only where the C# implementation is schema-driven JSON. Hand-write LLSD encodings. |
|
||||||
| MessagePack 3.1.8 | [`rmp-serde` 1.3.1](https://crates.io/crates/rmp-serde/1.3.1), [`rmpv` 1.3.1](https://crates.io/crates/rmpv/1.3.1) | Golden byte vectors must prove integer widths, maps, extensions, and field ordering. |
|
| MessagePack 3.1.8 | [`rmp-serde` 1.3.1](https://crates.io/crates/rmp-serde/1.3.1), [`rmpv` 1.3.1](https://crates.io/crates/rmpv/1.3.1) | Golden byte vectors must prove integer widths, maps, extensions, and field ordering. |
|
||||||
| UUID | [`uuid` 1.24.0](https://crates.io/crates/uuid/1.24.0) | Wrap it; do not expose dependency-specific endian assumptions as protocol behavior. |
|
| UUID | [`uuid` 1.24.0](https://crates.io/crates/uuid/1.24.0) | Wrap it; do not expose dependency-specific endian assumptions as protocol behavior. WASM selects UUID's `rng-getrandom` adapter and `getrandom`'s Web Crypto-backed `wasm_js` feature while desktop targets retain operating-system entropy. |
|
||||||
| byte buffers | [`bytes` 1.12.1](https://crates.io/crates/bytes/1.12.1), [`bytemuck` 1.25.2](https://crates.io/crates/bytemuck/1.25.2) | Prefer explicit endian reads. `bytemuck` is only for proven POD layouts, never untrusted variable packets. |
|
| byte buffers | [`bytes` 1.12.1](https://crates.io/crates/bytes/1.12.1), [`bytemuck` 1.25.2](https://crates.io/crates/bytemuck/1.25.2) | Prefer explicit endian reads. `bytemuck` is only for proven POD layouts, never untrusted variable packets. |
|
||||||
| vector/matrix math | [`glam` 0.33.3](https://crates.io/crates/glam/0.33.3) | Keep compatibility newtypes to control component order, precision, equality, and serialization. |
|
| vector/matrix math | [`glam` 0.33.3](https://crates.io/crates/glam/0.33.3) | Keep compatibility newtypes to control component order, precision, equality, and serialization. |
|
||||||
| flags | [`bitflags` 2.13.1](https://crates.io/crates/bitflags/2.13.1) | Retain unknown bits from newer grids. |
|
| flags | [`bitflags` 2.13.1](https://crates.io/crates/bitflags/2.13.1) | Retain unknown bits from newer grids. |
|
||||||
@@ -417,6 +417,7 @@ MSRV, features, and licenses at adoption time.
|
|||||||
| CoreJ2K 2.3.3.91 | system [OpenJPEG](https://www.openjpeg.org/) 2.5.4+ through the private `libremetaverse-openjpeg` adapter | Opt-in `jpeg2000` feature; checked-in minimal bindings avoid a libclang build dependency. Bounded memory streams and header validation isolate native code. Golden tests cover channel order, alpha, 16-bit precision, dimensions, discard levels, lossless/lossy modes, and malformed input. |
|
| CoreJ2K 2.3.3.91 | system [OpenJPEG](https://www.openjpeg.org/) 2.5.4+ through the private `libremetaverse-openjpeg` adapter | Opt-in `jpeg2000` feature; checked-in minimal bindings avoid a libclang build dependency. Bounded memory streams and header validation isolate native code. Golden tests cover channel order, alpha, 16-bit precision, dimensions, discard levels, lossless/lossy modes, and malformed input. |
|
||||||
| CoreJ2K pure-Rust extension | [`j2k`](https://crates.io/crates/j2k) 0.8.1 | Independent opt-in `rust-j2k` feature with no native library. The safe adapter provides J2K/JP2 encode/decode, native component preservation, bounded streams and allocations, reduced resolution, progressive quality layers, strict/permissive truncation, and OpenJPEG interoperability. |
|
| CoreJ2K pure-Rust extension | [`j2k`](https://crates.io/crates/j2k) 0.8.1 | Independent opt-in `rust-j2k` feature with no native library. The safe adapter provides J2K/JP2 encode/decode, native component preservation, bounded streams and allocations, reduced resolution, progressive quality layers, strict/permissive truncation, and OpenJPEG interoperability. |
|
||||||
| SkiaSharp 4.150.1 | [`skia-safe` 0.99.0](https://crates.io/crates/skia-safe/0.99.0) | Adopted behind the opt-in `skia` feature. Target-specific official binary-cache feature sets provide BMP/GIF/ICO/JPEG/PNG/WBMP/WebP decoding on macOS, Linux, and Windows; checked owned buffers keep Skia types out of the core image API. |
|
| SkiaSharp 4.150.1 | [`skia-safe` 0.99.0](https://crates.io/crates/skia-safe/0.99.0) | Adopted behind the opt-in `skia` feature. Target-specific official binary-cache feature sets provide BMP/GIF/ICO/JPEG/PNG/WBMP/WebP decoding on macOS, Linux, and Windows; checked owned buffers keep Skia types out of the core image API. |
|
||||||
|
| SkiaSharp pure-Rust extension | [`skia-rs-codec` 0.3.0](https://crates.io/crates/skia-rs-codec/0.3.0) and [`image-webp` 0.2.4](https://crates.io/crates/image-webp/0.2.4) | Independent opt-in `rust-skia` feature with no native codec. Default features stay disabled: pure-Rust PNG/JPEG/GIF plus built-in BMP/ICO/WBMP come from `skia-rs-codec`, and pure-Rust WebP comes from `image-webp` instead of the native `libwebp-sys` path. |
|
||||||
| Pfim 0.11.4 | [`image` 0.25.10](https://crates.io/crates/image/0.25.10), [`ddsfile` 0.6.0](https://crates.io/crates/ddsfile/0.6.0) | `image` covers TGA and common DDS decoding; `ddsfile` exposes DDS container details. Golden files decide whether both are needed. |
|
| Pfim 0.11.4 | [`image` 0.25.10](https://crates.io/crates/image/0.25.10), [`ddsfile` 0.6.0](https://crates.io/crates/ddsfile/0.6.0) | `image` covers TGA and common DDS decoding; `ddsfile` exposes DDS container details. Golden files decide whether both are needed. |
|
||||||
| OggVorbisEncoder 1.2.2 | [`vorbis_rs` 0.5.6](https://crates.io/crates/vorbis_rs/0.5.6) | BSD-3-Clause, MSRV 1.82, backed by C libraries. Feature-gate native audio encoding. |
|
| OggVorbisEncoder 1.2.2 | [`vorbis_rs` 0.5.6](https://crates.io/crates/vorbis_rs/0.5.6) | BSD-3-Clause, MSRV 1.82, backed by C libraries. Feature-gate native audio encoding. |
|
||||||
| SIPSorcery 8.0.23 | [`str0m` 0.22.0](https://crates.io/crates/str0m/0.22.0), [`cpal` 0.18.1](https://crates.io/crates/cpal/0.18.1), system libopus 1.3+ through `libremetaverse-opus` | The private safe adapter avoids the unmaintained `audiopus_sys` binding. Validate SDP, ICE, data-channel framing, audio formats, device hotplug, and native libopus deployment separately. Do not claim parity from successful compilation. |
|
| SIPSorcery 8.0.23 | [`str0m` 0.22.0](https://crates.io/crates/str0m/0.22.0), [`cpal` 0.18.1](https://crates.io/crates/cpal/0.18.1), system libopus 1.3+ through `libremetaverse-opus` | The private safe adapter avoids the unmaintained `audiopus_sys` binding. Validate SDP, ICE, data-channel framing, audio formats, device hotplug, and native libopus deployment separately. Do not claim parity from successful compilation. |
|
||||||
@@ -444,7 +445,7 @@ The current adopted set is:
|
|||||||
| Async and HTTP | `tokio`, `futures-channel`, `futures-util`, `reqwest` |
|
| Async and HTTP | `tokio`, `futures-channel`, `futures-util`, `reqwest` |
|
||||||
| Wire data and parsing | `base64`, `serde`, `serde_json`, `roxmltree`, `regex`, `unicode-general-category` |
|
| Wire data and parsing | `base64`, `serde`, `serde_json`, `roxmltree`, `regex`, `unicode-general-category` |
|
||||||
| Identity, hashing, and platform facts | `uuid`, `getrandom`, `md-5`, `sha1`, `sha2`, `mac_address2`, `os_info` |
|
| Identity, hashing, and platform facts | `uuid`, `getrandom`, `md-5`, `sha1`, `sha2`, `mac_address2`, `os_info` |
|
||||||
| Archives, images, and audio | `flate2`, `tar`, `bcdec_rs`, `skia-safe`, `hound`, `vorbis_rs`, `str0m`, `cpal` |
|
| Archives, images, and audio | `flate2`, `tar`, `bcdec_rs`, `skia-safe`, `skia-rs-codec`, `image-webp`, `hound`, `vorbis_rs`, `str0m`, `cpal` |
|
||||||
| Code generation, program CLI, and artifact inspection | `syn`, `prettyplease`, `clap`, `goblin` |
|
| Code generation, program CLI, and artifact inspection | `syn`, `prettyplease`, `clap`, `goblin` |
|
||||||
| Build and compatibility-test support | `pkg-config`, `vcpkg`, `stats_alloc` |
|
| Build and compatibility-test support | `pkg-config`, `vcpkg`, `stats_alloc` |
|
||||||
|
|
||||||
@@ -518,10 +519,12 @@ and invalid-dimension tests match the original.
|
|||||||
|
|
||||||
### 5.4 `libremetaverse-imaging-skia`
|
### 5.4 `libremetaverse-imaging-skia`
|
||||||
|
|
||||||
Implement `SkiaTextureCodec` as an optional adapter with `skia-safe`. Convert at
|
Implement `SkiaTextureCodec` as an optional adapter with `skia-safe`, plus an
|
||||||
the boundary to/from `ManagedImage`; never expose `skia_safe` types in the core
|
independently selectable `RustSkiaTextureCodec` using `skia-rs-codec` and
|
||||||
trait. CI must cover macOS, Linux, and Windows or explicitly document unsupported
|
`image-webp`. Convert at the boundary to/from `ManagedImage`; never expose
|
||||||
targets. Validate native binary provenance and packaging.
|
backend-specific types in the core trait. CI must cover macOS, Linux, Windows,
|
||||||
|
and the Rust-only WASM compile boundary. Validate native binary provenance and
|
||||||
|
the locked Rust dependency/license inventory.
|
||||||
|
|
||||||
### 5.5 `libremetaverse-prim-mesher`
|
### 5.5 `libremetaverse-prim-mesher`
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ The compatibility source is pinned at [`2aa70bb68513b39795da5d13c88f31b86e85a3ba
|
|||||||
| `libremetaverse-types` | 45 | 942 | 887 | none | `532cdfc175a60cb6ab109b2c43cfdda1d89cf0aadffccbcd7c9b18e1a3215bee` |
|
| `libremetaverse-types` | 45 | 942 | 887 | none | `532cdfc175a60cb6ab109b2c43cfdda1d89cf0aadffccbcd7c9b18e1a3215bee` |
|
||||||
| `libremetaverse-structured-data` | 16 | 295 | 304 | none | `b1c2ca9a683efe92ea22293384189f9e7c9a1926860893ab78c41829e641a8c3` |
|
| `libremetaverse-structured-data` | 16 | 295 | 304 | none | `b1c2ca9a683efe92ea22293384189f9e7c9a1926860893ab78c41829e641a8c3` |
|
||||||
| `libremetaverse-imaging` | 3 | 20 | 70 | default, jpeg2000, rust-j2k | `19423a5aec60e38d547b809ab947e7aff6366318f97f69cde824f57ae6194c0e` |
|
| `libremetaverse-imaging` | 3 | 20 | 70 | default, jpeg2000, rust-j2k | `19423a5aec60e38d547b809ab947e7aff6366318f97f69cde824f57ae6194c0e` |
|
||||||
| `libremetaverse-imaging-skia` | 1 | 3 | 13 | default, skia | `a6a1445725410a036204496ad4953c84dcfea1e6a00390ce4e10d12d36f2876b` |
|
| `libremetaverse-imaging-skia` | 1 | 3 | 17 | default, rust-skia, skia | `855a181b77413a1e5f0094b1581971fd5e0a4d93fadb5f83d54f82a7ba8ee71f` |
|
||||||
| `libremetaverse-prim-mesher` | 17 | 207 | 117 | none | `dde798e86c485948f1d67e093f8194a76082101416516df3f8dca4de04c2d415` |
|
| `libremetaverse-prim-mesher` | 17 | 207 | 117 | none | `dde798e86c485948f1d67e093f8194a76082101416516df3f8dca4de04c2d415` |
|
||||||
| `libremetaverse-rendering-simple` | 1 | 6 | 12 | none | `4dc284ea0abb16de63494435758c8b7c5eeb57a80d2e32a141e488e5861f2fad` |
|
| `libremetaverse-rendering-simple` | 1 | 6 | 12 | none | `4dc284ea0abb16de63494435758c8b7c5eeb57a80d2e32a141e488e5861f2fad` |
|
||||||
| `libremetaverse-rendering-mesh-foundry` | 1 | 14 | 25 | none | `3689f6b454061fdae699d5fb66a11482909fa25bda398e26c38327995a9e2896` |
|
| `libremetaverse-rendering-mesh-foundry` | 1 | 14 | 25 | none | `3689f6b454061fdae699d5fb66a11482909fa25bda398e26c38327995a9e2896` |
|
||||||
@@ -46,7 +46,7 @@ The exact mapping, exported-marker, feature, and normalized Rust declaration has
|
|||||||
- .NET events become `subscribe_*` calls returning an owned `Subscription`; callbacks are `Send + Sync` and dispatch outside internal locks.
|
- .NET events become `subscribe_*` calls returning an owned `Subscription`; callbacks are `Send + Sync` and dispatch outside internal locks.
|
||||||
- `IDisposable` becomes explicit idempotent shutdown plus `Drop`; cancellation remains a typed `Error::Cancelled`.
|
- `IDisposable` becomes explicit idempotent shutdown plus `Drop`; cancellation remains a typed `Error::Cancelled`.
|
||||||
- Closed C# enums retain fixed discriminants and are SemVer-breaking to extend; flags retain unknown bits, while public Rust error enums are `non_exhaustive`.
|
- Closed C# enums retain fixed discriminants and are SemVer-breaking to extend; flags retain unknown bits, while public Rust error enums are `non_exhaustive`.
|
||||||
- Optional native backends remain feature-gated (`jpeg2000`, `skia`, `vorbis`, `real-audio`); default and empty-default sets are part of the baseline.
|
- Optional native and pure-Rust backends remain feature-gated (`jpeg2000`, `rust-j2k`, `skia`, `rust-skia`, `vorbis`, `real-audio`); default and empty-default sets are part of the baseline.
|
||||||
- Capability HTTP injection uses project-owned `HttpMessageHandler`, `CapsHttpLimits`, and `with_native_transport`; the internal `reqwest` client is not part of the public surface.
|
- Capability HTTP injection uses project-owned `HttpMessageHandler`, `CapsHttpLimits`, and `with_native_transport`; the internal `reqwest` client is not part of the public surface.
|
||||||
- External C# signature types map to core/std, adopted cross-platform crates, or project-owned boundary types; no third-party crate path leaks through mapped signatures or public Rust declarations.
|
- External C# signature types map to core/std, adopted cross-platform crates, or project-owned boundary types; no third-party crate path leaks through mapped signatures or public Rust declarations.
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"type_mapping_sha256": "21025889c62b0f8666a2dda46a03ff4f28931f51156927822a1c04e97b49f221",
|
"type_mapping_sha256": "21025889c62b0f8666a2dda46a03ff4f28931f51156927822a1c04e97b49f221",
|
||||||
"member_mapping_sha256": "cd99420643c665ea393dd59418c33fb00f97f7030e71540c00b2b27470abb1d4",
|
"member_mapping_sha256": "cd99420643c665ea393dd59418c33fb00f97f7030e71540c00b2b27470abb1d4",
|
||||||
"exported_mapping_sha256": "5b8a502ce229d26732744f2b44c029fc4a86b403966dc2f9b4a1c913a7b242b9",
|
"exported_mapping_sha256": "5b8a502ce229d26732744f2b44c029fc4a86b403966dc2f9b4a1c913a7b242b9",
|
||||||
"rust_declaration_sha256": "687d3d29bb0e79651881ffdda962be21df8716a4d96417175611541d0fe27a8e",
|
"rust_declaration_sha256": "b2ba1ccf9293ac94164e593546891a2a122b1e5997ee4ecc2de86ef5eb0d866e",
|
||||||
"crates": [
|
"crates": [
|
||||||
{
|
{
|
||||||
"name": "libremetaverse",
|
"name": "libremetaverse",
|
||||||
@@ -87,14 +87,21 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"features": {
|
"features": {
|
||||||
"default": [],
|
"default": [],
|
||||||
|
"rust-skia": [
|
||||||
|
"dep:image-webp",
|
||||||
|
"dep:skia-rs-codec",
|
||||||
|
"skia-rs-codec/gif",
|
||||||
|
"skia-rs-codec/jpeg",
|
||||||
|
"skia-rs-codec/png"
|
||||||
|
],
|
||||||
"skia": [
|
"skia": [
|
||||||
"dep:skia-safe"
|
"dep:skia-safe"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mapped_types": 1,
|
"mapped_types": 1,
|
||||||
"mapped_members": 3,
|
"mapped_members": 3,
|
||||||
"public_declarations": 13,
|
"public_declarations": 17,
|
||||||
"declaration_sha256": "a6a1445725410a036204496ad4953c84dcfea1e6a00390ce4e10d12d36f2876b"
|
"declaration_sha256": "855a181b77413a1e5f0094b1581971fd5e0a4d93fadb5f83d54f82a7ba8ee71f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "libremetaverse-prim-mesher",
|
"name": "libremetaverse-prim-mesher",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
"minimal-features",
|
"minimal-features",
|
||||||
"jpeg2000",
|
"jpeg2000",
|
||||||
"rust-j2k",
|
"rust-j2k",
|
||||||
|
"rust-skia",
|
||||||
"skia-binary",
|
"skia-binary",
|
||||||
"program-offline-smoke",
|
"program-offline-smoke",
|
||||||
"clippy",
|
"clippy",
|
||||||
@@ -104,8 +105,8 @@
|
|||||||
"workflow": "skia.yml",
|
"workflow": "skia.yml",
|
||||||
"responsibility": "Default and Skia feature tests plus package listing",
|
"responsibility": "Default and Skia feature tests plus package listing",
|
||||||
"destination": "required",
|
"destination": "required",
|
||||||
"checks": ["skia-binary", "workspace-tests"],
|
"checks": ["rust-skia", "skia-binary", "workspace-tests"],
|
||||||
"rationale": "The required gate proves the exact ARM64 GNU archive is installed and forbids source compilation."
|
"rationale": "A dedicated dependency-free job tests the Rust-only codec graph, while the required gate proves the exact ARM64 GNU archive is installed and forbids source compilation."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"workflow": "supply-chain.yml",
|
"workflow": "supply-chain.yml",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"schema": 1,
|
"schema": 1,
|
||||||
"msrv": "1.96.0",
|
"msrv": "1.96.0",
|
||||||
"current": "stable",
|
"current": "stable",
|
||||||
"reviewed_on": "2026-08-12",
|
"reviewed_on": "2026-08-13",
|
||||||
"review_by": "2026-11-11",
|
"review_by": "2026-11-11",
|
||||||
"direct": [
|
"direct": [
|
||||||
{ "name": "base64", "versions": ["0.22.1"], "purpose": "LLSD, login, asset, and protocol base64 encoding", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`base64`" },
|
{ "name": "base64", "versions": ["0.22.1"], "purpose": "LLSD, login, asset, and protocol base64 encoding", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`base64`" },
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
{ "name": "getrandom", "versions": ["0.4.3"], "purpose": "Operating-system entropy for protocol identifiers", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`getrandom`" },
|
{ "name": "getrandom", "versions": ["0.4.3"], "purpose": "Operating-system entropy for protocol identifiers", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`getrandom`" },
|
||||||
{ "name": "goblin", "versions": ["0.10.5"], "purpose": "Cross-platform ELF, PE, and Mach-O release artifact inspection", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`goblin`" },
|
{ "name": "goblin", "versions": ["0.10.5"], "purpose": "Cross-platform ELF, PE, and Mach-O release artifact inspection", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`goblin`" },
|
||||||
{ "name": "hound", "versions": ["3.5.1"], "purpose": "Bounded PCM WAV parsing for WebRTC playback", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`hound`" },
|
{ "name": "hound", "versions": ["3.5.1"], "purpose": "Bounded PCM WAV parsing for WebRTC playback", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`hound`" },
|
||||||
|
{ "name": "image-webp", "versions": ["0.2.4"], "purpose": "Opt-in pure-Rust bounded WebP image decoding", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`image-webp`" },
|
||||||
{ "name": "j2k", "versions": ["0.8.1"], "purpose": "Opt-in pure-Rust bounded JPEG 2000 and JP2 encoding and decoding", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`j2k`" },
|
{ "name": "j2k", "versions": ["0.8.1"], "purpose": "Opt-in pure-Rust bounded JPEG 2000 and JP2 encoding and decoding", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`j2k`" },
|
||||||
{ "name": "mac_address2", "versions": ["2.0.2"], "purpose": "Cross-platform machine identity compatibility input", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`mac_address2`" },
|
{ "name": "mac_address2", "versions": ["2.0.2"], "purpose": "Cross-platform machine identity compatibility input", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`mac_address2`" },
|
||||||
{ "name": "md-5", "versions": ["0.10.6"], "purpose": "Legacy protocol checksum compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`md-5`" },
|
{ "name": "md-5", "versions": ["0.10.6"], "purpose": "Legacy protocol checksum compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`md-5`" },
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
{ "name": "sha1", "versions": ["0.10.7"], "purpose": "Legacy protocol hash compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha1`" },
|
{ "name": "sha1", "versions": ["0.10.7"], "purpose": "Legacy protocol hash compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha1`" },
|
||||||
{ "name": "sha2", "versions": ["0.11.0"], "purpose": "Manifest integrity and protocol hashing", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha2`" },
|
{ "name": "sha2", "versions": ["0.11.0"], "purpose": "Manifest integrity and protocol hashing", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha2`" },
|
||||||
{ "name": "skia-safe", "versions": ["0.99.0"], "purpose": "Opt-in cross-platform Skia image decoding", "maintenance": "monitored-native", "transitive_cost": "high", "native": true, "rewrite_anchor": "`skia-safe`" },
|
{ "name": "skia-safe", "versions": ["0.99.0"], "purpose": "Opt-in cross-platform Skia image decoding", "maintenance": "monitored-native", "transitive_cost": "high", "native": true, "rewrite_anchor": "`skia-safe`" },
|
||||||
|
{ "name": "skia-rs-codec", "versions": ["0.3.0"], "purpose": "Opt-in pure-Rust BMP, GIF, ICO, JPEG, PNG, and WBMP image decoding", "maintenance": "active", "transitive_cost": "high", "native": false, "rewrite_anchor": "`skia-rs-codec`" },
|
||||||
{ "name": "stats_alloc", "versions": ["0.1.10"], "purpose": "Allocation-budget compatibility tests, concurrency leak audits, and reproducible performance evidence", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`stats_alloc`" },
|
{ "name": "stats_alloc", "versions": ["0.1.10"], "purpose": "Allocation-budget compatibility tests, concurrency leak audits, and reproducible performance evidence", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`stats_alloc`" },
|
||||||
{ "name": "str0m", "versions": ["0.22.0"], "purpose": "Native Rust ICE, DTLS, SRTP, RTP, and SCTP WebRTC transport", "maintenance": "active", "transitive_cost": "high", "native": false, "rewrite_anchor": "`str0m`" },
|
{ "name": "str0m", "versions": ["0.22.0"], "purpose": "Native Rust ICE, DTLS, SRTP, RTP, and SCTP WebRTC transport", "maintenance": "active", "transitive_cost": "high", "native": false, "rewrite_anchor": "`str0m`" },
|
||||||
{ "name": "syn", "versions": ["2.0.119"], "purpose": "Syntax validation for generated Rust sources", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`syn`" },
|
{ "name": "syn", "versions": ["2.0.119"], "purpose": "Syntax validation for generated Rust sources", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`syn`" },
|
||||||
@@ -40,6 +42,8 @@
|
|||||||
{ "name": "vorbis_rs", "versions": ["0.5.6"], "purpose": "Opt-in Ogg Vorbis asset encoding", "maintenance": "monitored-native", "transitive_cost": "medium", "native": true, "rewrite_anchor": "`vorbis_rs`" }
|
{ "name": "vorbis_rs", "versions": ["0.5.6"], "purpose": "Opt-in Ogg Vorbis asset encoding", "maintenance": "monitored-native", "transitive_cost": "medium", "native": true, "rewrite_anchor": "`vorbis_rs`" }
|
||||||
],
|
],
|
||||||
"approved_duplicates": [
|
"approved_duplicates": [
|
||||||
|
{ "name": "bit-vec", "versions": ["0.8.0", "0.9.1"], "reason": "The pinned skia-rs shader parser and current WebRTC certificate stack require adjacent bit-vector API lines." },
|
||||||
|
{ "name": "bitflags", "versions": ["1.3.2", "2.13.1"], "reason": "The pinned pure-Rust PNG codec remains on bitflags 1 while the rest of the workspace uses bitflags 2." },
|
||||||
{ "name": "block-buffer", "versions": ["0.10.4", "0.12.1"], "reason": "RustCrypto digest 0.10 and 0.11 consumers have not unified their block-buffer major version." },
|
{ "name": "block-buffer", "versions": ["0.10.4", "0.12.1"], "reason": "RustCrypto digest 0.10 and 0.11 consumers have not unified their block-buffer major version." },
|
||||||
{ "name": "cfg_aliases", "versions": ["0.1.1", "0.2.2"], "reason": "The target-specific native stacks use different nix-generation build helpers." },
|
{ "name": "cfg_aliases", "versions": ["0.1.1", "0.2.2"], "reason": "The target-specific native stacks use different nix-generation build helpers." },
|
||||||
{ "name": "chacha20", "versions": ["0.9.1", "0.10.1"], "reason": "The WebRTC crypto and current random-number stacks require different RustCrypto generations." },
|
{ "name": "chacha20", "versions": ["0.9.1", "0.10.1"], "reason": "The WebRTC crypto and current random-number stacks require different RustCrypto generations." },
|
||||||
@@ -48,12 +52,14 @@
|
|||||||
{ "name": "crypto-common", "versions": ["0.1.7", "0.2.2"], "reason": "Legacy protocol hashes and current SHA-2 intentionally span RustCrypto digest generations." },
|
{ "name": "crypto-common", "versions": ["0.1.7", "0.2.2"], "reason": "Legacy protocol hashes and current SHA-2 intentionally span RustCrypto digest generations." },
|
||||||
{ "name": "digest", "versions": ["0.10.7", "0.11.3"], "reason": "MD5, SHA-1, and WebRTC use digest 0.10 while manifest SHA-2 uses the audited 0.11 API." },
|
{ "name": "digest", "versions": ["0.10.7", "0.11.3"], "reason": "MD5, SHA-1, and WebRTC use digest 0.10 while manifest SHA-2 uses the audited 0.11 API." },
|
||||||
{ "name": "getrandom", "versions": ["0.2.17", "0.3.4", "0.4.3"], "reason": "WebRTC crypto, transitive rand, and direct UUID entropy consumers span three compatible APIs." },
|
{ "name": "getrandom", "versions": ["0.2.17", "0.3.4", "0.4.3"], "reason": "WebRTC crypto, transitive rand, and direct UUID entropy consumers span three compatible APIs." },
|
||||||
|
{ "name": "hashbrown", "versions": ["0.16.1", "0.17.1"], "reason": "The pinned skia-rs geometry and shader dependencies have not unified their hash table minor line." },
|
||||||
{ "name": "jni-sys", "versions": ["0.3.1", "0.4.1"], "reason": "CPAL Android NDK support and rustls Android certificate verification require different JNI bindings." },
|
{ "name": "jni-sys", "versions": ["0.3.1", "0.4.1"], "reason": "CPAL Android NDK support and rustls Android certificate verification require different JNI bindings." },
|
||||||
{ "name": "nix", "versions": ["0.28.0", "0.31.3"], "reason": "Machine-address and operating-system reporting crates have not unified their Unix API generation." },
|
{ "name": "nix", "versions": ["0.28.0", "0.31.3"], "reason": "Machine-address and operating-system reporting crates have not unified their Unix API generation." },
|
||||||
{ "name": "nom", "versions": ["7.1.3", "8.0.0"], "reason": "Skia bindgen tooling remains on nom 7 while the native WebRTC stack uses nom 8." },
|
{ "name": "nom", "versions": ["7.1.3", "8.0.0"], "reason": "Skia bindgen tooling remains on nom 7 while the native WebRTC stack uses nom 8." },
|
||||||
{ "name": "r-efi", "versions": ["5.3.0", "6.0.0"], "reason": "The three resolved getrandom generations require two WASI EFI interface generations." },
|
{ "name": "r-efi", "versions": ["5.3.0", "6.0.0"], "reason": "The three resolved getrandom generations require two WASI EFI interface generations." },
|
||||||
{ "name": "rand", "versions": ["0.9.5", "0.10.2"], "reason": "WebRTC protocol crates use rand 0.9 while target-specific dependencies have adopted rand 0.10." },
|
{ "name": "rand", "versions": ["0.9.5", "0.10.2"], "reason": "WebRTC protocol crates use rand 0.9 while target-specific dependencies have adopted rand 0.10." },
|
||||||
{ "name": "rand_core", "versions": ["0.6.4", "0.9.5", "0.10.1"], "reason": "DTLS elliptic curves and the two resolved rand generations require distinct rand_core APIs." },
|
{ "name": "rand_core", "versions": ["0.6.4", "0.9.5", "0.10.1"], "reason": "DTLS elliptic curves and the two resolved rand generations require distinct rand_core APIs." },
|
||||||
|
{ "name": "rustc-hash", "versions": ["1.1.0", "2.1.3"], "reason": "The pinned skia-rs shader parser remains on rustc-hash 1 while existing workspace parsers use version 2." },
|
||||||
{ "name": "sha2", "versions": ["0.10.9", "0.11.0"], "reason": "WebRTC crypto still requires SHA-2 0.10 while MetaCrate integrity code directly uses 0.11." },
|
{ "name": "sha2", "versions": ["0.10.9", "0.11.0"], "reason": "WebRTC crypto still requires SHA-2 0.10 while MetaCrate integrity code directly uses 0.11." },
|
||||||
{ "name": "shlex", "versions": ["1.3.0", "2.0.1"], "reason": "Skia bindgen and current native C compilation helpers use different shell-token parsers." },
|
{ "name": "shlex", "versions": ["1.3.0", "2.0.1"], "reason": "Skia bindgen and current native C compilation helpers use different shell-token parsers." },
|
||||||
{ "name": "syn", "versions": ["2.0.119", "3.0.3"], "reason": "MetaCrate code generation uses syn 2 while current derive macro dependencies use syn 3." },
|
{ "name": "syn", "versions": ["2.0.119", "3.0.3"], "reason": "MetaCrate code generation uses syn 2 while current derive macro dependencies use syn 3." },
|
||||||
|
|||||||
@@ -42,12 +42,12 @@
|
|||||||
"execution": "native",
|
"execution": "native",
|
||||||
"toolchain": "1.96.0",
|
"toolchain": "1.96.0",
|
||||||
"target": "x86_64-unknown-linux-gnu",
|
"target": "x86_64-unknown-linux-gnu",
|
||||||
"feature_sets": ["no-default-features", "rust-j2k"],
|
"feature_sets": ["no-default-features", "rust-j2k", "rust-skia"],
|
||||||
"prerequisites": ["libopus-1.3"],
|
"prerequisites": ["libopus-1.3"],
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"label": "Compile the portable public crates on the declared MSRV",
|
"label": "Compile the portable public crates on the declared MSRV",
|
||||||
"args": ["check", "--locked", "-j", "1", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
"args": ["check", "--locked", "-j", "1", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k,libremetaverse-imaging-skia/rust-skia", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Compile the safe native Opus boundary and WebRTC voice on the declared MSRV",
|
"label": "Compile the safe native Opus boundary and WebRTC voice on the declared MSRV",
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
"execution": "native",
|
"execution": "native",
|
||||||
"toolchain": "stable",
|
"toolchain": "stable",
|
||||||
"target": "x86_64-unknown-linux-gnu",
|
"target": "x86_64-unknown-linux-gnu",
|
||||||
"feature_sets": ["all-features", "dds-bc67", "jpeg2000", "rust-j2k", "skia", "vorbis", "real-audio", "tests"],
|
"feature_sets": ["all-features", "dds-bc67", "jpeg2000", "rust-j2k", "rust-skia", "skia", "vorbis", "real-audio", "tests"],
|
||||||
"prerequisites": ["openjpeg-2.5.4", "skia-safe-0.99.0", "libopus-1.3", "alsa-1.2", "vorbis-rs-0.5.6"],
|
"prerequisites": ["openjpeg-2.5.4", "skia-safe-0.99.0", "libopus-1.3", "alsa-1.2", "vorbis-rs-0.5.6"],
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
@@ -125,10 +125,18 @@
|
|||||||
"label": "Test OpenJPEG and pure-Rust JPEG 2000 interoperability",
|
"label": "Test OpenJPEG and pure-Rust JPEG 2000 interoperability",
|
||||||
"args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "jpeg2000,rust-j2k", "--locked", "-j", "1"]
|
"args": ["test", "-p", "libremetaverse-imaging", "--no-default-features", "--features", "jpeg2000,rust-j2k", "--locked", "-j", "1"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Test the pure-Rust Skia-compatible feature independently",
|
||||||
|
"args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "rust-skia", "--locked", "-j", "1"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Test the Skia feature independently",
|
"label": "Test the Skia feature independently",
|
||||||
"args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "skia", "--locked", "-j", "1"]
|
"args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "skia", "--locked", "-j", "1"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Test native Skia and pure-Rust codec interoperability",
|
||||||
|
"args": ["test", "-p", "libremetaverse-imaging-skia", "--no-default-features", "--features", "skia,rust-skia", "--locked", "-j", "1"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Test the Vorbis feature independently",
|
"label": "Test the Vorbis feature independently",
|
||||||
"args": ["test", "-p", "libremetaverse", "--no-default-features", "--features", "vorbis", "--lib", "--locked", "-j", "1", "--", "asset_pipeline_semantics"]
|
"args": ["test", "-p", "libremetaverse", "--no-default-features", "--features", "vorbis", "--lib", "--locked", "-j", "1", "--", "asset_pipeline_semantics"]
|
||||||
@@ -170,12 +178,12 @@
|
|||||||
"execution": "cross",
|
"execution": "cross",
|
||||||
"toolchain": "stable",
|
"toolchain": "stable",
|
||||||
"target": "x86_64-pc-windows-gnu",
|
"target": "x86_64-pc-windows-gnu",
|
||||||
"feature_sets": ["no-default-features", "dds-bc67", "rust-j2k"],
|
"feature_sets": ["no-default-features", "dds-bc67", "rust-j2k", "rust-skia"],
|
||||||
"prerequisites": [],
|
"prerequisites": [],
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"label": "Cross-check portable crates for Windows GNU",
|
"label": "Cross-check portable crates for Windows GNU",
|
||||||
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-pc-windows-gnu", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-pc-windows-gnu", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k,libremetaverse-imaging-skia/rust-skia", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -186,12 +194,12 @@
|
|||||||
"execution": "cross",
|
"execution": "cross",
|
||||||
"toolchain": "stable",
|
"toolchain": "stable",
|
||||||
"target": "x86_64-apple-darwin",
|
"target": "x86_64-apple-darwin",
|
||||||
"feature_sets": ["no-default-features", "dds-bc67", "rust-j2k"],
|
"feature_sets": ["no-default-features", "dds-bc67", "rust-j2k", "rust-skia"],
|
||||||
"prerequisites": [],
|
"prerequisites": [],
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"label": "Cross-check portable crates for macOS",
|
"label": "Cross-check portable crates for macOS",
|
||||||
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-apple-darwin", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
"args": ["check", "--locked", "-j", "1", "--target", "x86_64-apple-darwin", "--all-targets", "--no-default-features", "--features", "libremetaverse-imaging/rust-j2k,libremetaverse-imaging-skia/rust-skia", "-p", "libremetaverse-types", "-p", "libremetaverse-structured-data", "-p", "libremetaverse-imaging", "-p", "libremetaverse-imaging-skia", "-p", "libremetaverse-prim-mesher", "-p", "libremetaverse-lsl-tools", "-p", "libremetaverse-rlv", "-p", "metacrate-ci-matrix"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ description = "Optional Skia image decoder for the MetaCrate LibreMetaverse rewr
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
skia = ["dep:skia-safe"]
|
skia = ["dep:skia-safe"]
|
||||||
|
rust-skia = ["dep:image-webp", "dep:skia-rs-codec", "skia-rs-codec/gif", "skia-rs-codec/jpeg", "skia-rs-codec/png"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
libremetaverse-imaging = { version = "0.0.1", path = "../libremetaverse-imaging" }
|
||||||
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||||
|
image-webp = { version = "=0.2.4", optional = true }
|
||||||
|
skia-rs-codec = { version = "=0.3.0", default-features = false, optional = true }
|
||||||
|
|
||||||
# rust-skia publishes WebP-capable binary caches with Vulkan on Linux/Windows
|
# rust-skia publishes WebP-capable binary caches with Vulkan on Linux/Windows
|
||||||
# and without Vulkan on macOS. Matching those sets avoids an hours-long Skia
|
# and without Vulkan on macOS. Matching those sets avoids an hours-long Skia
|
||||||
|
|||||||
@@ -6,10 +6,43 @@ exposes a `skia-safe` type and never discovers or links Skia.
|
|||||||
|
|
||||||
## Features and formats
|
## Features and formats
|
||||||
|
|
||||||
The default feature set has no Skia dependency. `SkiaTextureCodec::decode`
|
The default feature set has no Skia dependency. `SkiaTextureCodec::decode` and
|
||||||
returns a typed `InvalidOperation` error in that configuration, while conversion
|
`RustSkiaTextureCodec::decode` return a typed `InvalidOperation` error when
|
||||||
from the checked project-owned `backend::SKBitmap` remains available for tests
|
their respective feature is disabled, while conversion from the checked
|
||||||
and callers that already own decoded pixels.
|
project-owned `backend::SKBitmap` remains available for tests and callers that
|
||||||
|
already own decoded pixels.
|
||||||
|
|
||||||
|
For a fully Rust implementation, enable:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo test -p libremetaverse-imaging-skia --no-default-features --features rust-skia
|
||||||
|
```
|
||||||
|
|
||||||
|
`rust-skia` pins [`skia-rs-codec` 0.3.0](https://github.com/rust-skia/skia-rs)
|
||||||
|
with default features disabled and only
|
||||||
|
its pure-Rust PNG, JPEG, and GIF codecs selected. Its `webp` feature is
|
||||||
|
deliberately disabled because that feature selects `libwebp-sys`; WebP is
|
||||||
|
instead decoded by the separately pinned, safe-Rust
|
||||||
|
[`image-webp` 0.2.4](https://github.com/image-rs/image-webp) crate.
|
||||||
|
BMP, ICO, and WBMP are built into `skia-rs-codec`. The resulting normal/build
|
||||||
|
graph has no codec `-sys` crate, C/C++ compilation, CMake, system-library
|
||||||
|
lookup, or binary download.
|
||||||
|
|
||||||
|
The locked transitive codec lines are `png` 0.17.16, `jpeg-decoder` 0.3.2,
|
||||||
|
`jpeg-encoder` 0.6.1 (the upstream JPEG feature couples decode and encode), and
|
||||||
|
`gif` 0.13.3. `skia-rs-codec` also brings its ordinary Rust core, paint, and
|
||||||
|
path crates; their build helpers only select Rust cfgs and compile no native
|
||||||
|
code. A source audit of the locked `skia-rs-*` crates found no unsafe blocks,
|
||||||
|
and `image-webp` declares `forbid(unsafe_code)`. MetaCrate itself continues to
|
||||||
|
compile with workspace `unsafe_code = "forbid"`.
|
||||||
|
|
||||||
|
`RustSkiaTextureCodec` implements the same `ITextureCodec` abstraction and
|
||||||
|
decodes BMP, GIF, ICO, baseline/progressive JPEG, interlaced PNG, WBMP, and
|
||||||
|
lossless/lossy/animated WebP. GIF and WebP return frame one composited on the
|
||||||
|
logical canvas; ICO chooses its largest valid entry. Both Skia features may be
|
||||||
|
enabled together, and each codec remains independently constructible.
|
||||||
|
The graph builds on the workspace Rust 1.96 MSRV; both selected direct codecs
|
||||||
|
declare older compatible Rust floors.
|
||||||
|
|
||||||
Enable native decoding with:
|
Enable native decoding with:
|
||||||
|
|
||||||
@@ -17,7 +50,7 @@ Enable native decoding with:
|
|||||||
cargo test -p libremetaverse-imaging-skia --features skia
|
cargo test -p libremetaverse-imaging-skia --features skia
|
||||||
```
|
```
|
||||||
|
|
||||||
The `skia` feature decodes the CPU codec formats supported by the pinned
|
The native `skia` feature decodes the CPU codec formats supported by the pinned
|
||||||
rust-skia release: BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP. Input is buffered
|
rust-skia release: BMP, GIF, ICO, JPEG, PNG, WBMP, and WebP. Input is buffered
|
||||||
to at most 64 MiB. Dimensions are rejected before native pixel allocation when
|
to at most 64 MiB. Dimensions are rejected before native pixel allocation when
|
||||||
they exceed the core 16,777,216-pixel limit, and decoded storage uses checked
|
they exceed the core 16,777,216-pixel limit, and decoded storage uses checked
|
||||||
@@ -31,6 +64,25 @@ alpha at this boundary. RGB565, BGRA8888, RGBA8888, RGBA/BGRA1010102, Gray8,
|
|||||||
Alpha8, row padding, and the reference byte-width fallback retain the pinned
|
Alpha8, row padding, and the reference byte-width fallback retain the pinned
|
||||||
C# channel and rounding rules.
|
C# channel and rounding rules.
|
||||||
|
|
||||||
|
Both paths accept any `ReadWrite + Send` stream and stop buffering after 64
|
||||||
|
MiB plus one sentinel byte. The pure-Rust path probes encoded dimensions before
|
||||||
|
codec pixel allocation and enforces the shared 16,777,216-pixel ceiling; WebP
|
||||||
|
also receives an explicit decoder memory limit. Checked dimensions, strides,
|
||||||
|
buffer sizes, and fallible project-owned allocations turn malformed,
|
||||||
|
truncated, oversized, and allocation failures into typed errors. Decoded rows
|
||||||
|
have a top-left origin and premultiplied native samples are normalized to
|
||||||
|
straight alpha at the shared `ManagedImage` boundary.
|
||||||
|
|
||||||
|
The pure-Rust graph has identical code on Linux, Windows, macOS, and WASM and
|
||||||
|
does not call platform APIs. Checked static fixtures cover top-down/bottom-up
|
||||||
|
BMP, palette/offset GIF, largest-entry ICO, baseline/progressive JPEG,
|
||||||
|
interlaced palette PNG, multibyte WBMP, lossless-alpha/lossy WebP, malformed and
|
||||||
|
oversized inputs, and concurrent decode/drop. Gitea runs the `rust-skia` suite
|
||||||
|
in a dedicated `ubuntu-latest` job that installs no native codec prerequisites.
|
||||||
|
`image-webp` 0.2's animated-canvas blend fast path rounds fully opaque nonzero
|
||||||
|
samples one low; the bounded adapter corrects that single upstream edge so the
|
||||||
|
checked first-frame planes remain byte-identical to native Skia.
|
||||||
|
|
||||||
## Binary cache and source builds
|
## Binary cache and source builds
|
||||||
|
|
||||||
`skia-safe` 0.99.0 downloads an official prebuilt Skia archive when the target
|
`skia-safe` 0.99.0 downloads an official prebuilt Skia archive when the target
|
||||||
@@ -66,3 +118,8 @@ explicitly.
|
|||||||
is BSD-3-Clause licensed. Official binary-cache archives contain compiled Skia.
|
is BSD-3-Clause licensed. Official binary-cache archives contain compiled Skia.
|
||||||
Products that redistribute the resulting native artifacts must preserve the
|
Products that redistribute the resulting native artifacts must preserve the
|
||||||
applicable MIT and BSD notices and audit the exact archive they ship.
|
applicable MIT and BSD notices and audit the exact archive they ship.
|
||||||
|
|
||||||
|
`skia-rs-codec` is MIT OR Apache-2.0 and `image-webp` is MIT OR Apache-2.0.
|
||||||
|
They are ordinary Rust source dependencies recorded in `Cargo.lock`; generated
|
||||||
|
dependency notices and the distribution manifest bind their crates.io checksums
|
||||||
|
and license texts for source and binary redistribution.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Optional Skia imaging adapter corresponding to `LibreMetaverse.Imaging.Skia`.
|
//! Optional Skia imaging adapter corresponding to `LibreMetaverse.Imaging.Skia`.
|
||||||
//!
|
//!
|
||||||
//! Enable `skia` for bounded `BMP`, `GIF`, `ICO`, `JPEG`, `PNG`, `WBMP`, and
|
//! Enable `skia` or the fully native-Rust `rust-skia` alternative for bounded
|
||||||
//! `WebP` decoding.
|
//! `BMP`, `GIF`, `ICO`, `JPEG`, `PNG`, `WBMP`, and `WebP` decoding.
|
||||||
//! The default build remains inert. See the crate README for native cache,
|
//! The default build remains inert. See the crate README for native cache,
|
||||||
//! source-build, licensing, and cross-platform prerequisite details.
|
//! source-build, licensing, and cross-platform prerequisite details.
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ mod skia_codec;
|
|||||||
pub use generated::*;
|
pub use generated::*;
|
||||||
pub use libremetaverse_imaging as imaging;
|
pub use libremetaverse_imaging as imaging;
|
||||||
pub use libremetaverse_types::Error;
|
pub use libremetaverse_types::Error;
|
||||||
|
pub use skia_codec::RustSkiaTextureCodec;
|
||||||
|
|
||||||
impl libremetaverse_imaging::ITextureCodec for SkiaTextureCodec {
|
impl libremetaverse_imaging::ITextureCodec for SkiaTextureCodec {
|
||||||
fn decode(
|
fn decode(
|
||||||
@@ -24,3 +25,12 @@ impl libremetaverse_imaging::ITextureCodec for SkiaTextureCodec {
|
|||||||
Self::decode(self, stream)
|
Self::decode(self, stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl libremetaverse_imaging::ITextureCodec for RustSkiaTextureCodec {
|
||||||
|
fn decode(
|
||||||
|
&self,
|
||||||
|
stream: Box<dyn libremetaverse_types::compat::ReadWrite + Send>,
|
||||||
|
) -> Result<libremetaverse_imaging::ManagedImage, Error> {
|
||||||
|
Self::decode(self, stream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,17 +2,24 @@
|
|||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::backend::{SKAlphaType, SKBitmap, SKColorType};
|
use crate::backend::{SKAlphaType, SKBitmap, SKColorType};
|
||||||
#[cfg(feature = "skia")]
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
use libremetaverse_imaging::{DEFAULT_MAX_ENCODED_BYTES, DEFAULT_MAX_PIXELS};
|
use libremetaverse_imaging::{DEFAULT_MAX_ENCODED_BYTES, DEFAULT_MAX_PIXELS};
|
||||||
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
|
use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
|
||||||
use libremetaverse_types::compat::ReadWrite;
|
use libremetaverse_types::compat::ReadWrite;
|
||||||
#[cfg(feature = "skia")]
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
/// Optional Skia-backed decoder and format-neutral bitmap converter.
|
/// Optional Skia-backed decoder and format-neutral bitmap converter.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct SkiaTextureCodec;
|
pub struct SkiaTextureCodec;
|
||||||
|
|
||||||
|
/// Pure-Rust alternative to [`SkiaTextureCodec`] with the same image boundary.
|
||||||
|
///
|
||||||
|
/// Enable the `rust-skia` feature to decode the common Skia codec formats
|
||||||
|
/// without a native library, build script, system package lookup, or download.
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
pub struct RustSkiaTextureCodec;
|
||||||
|
|
||||||
impl SkiaTextureCodec {
|
impl SkiaTextureCodec {
|
||||||
/// Creates the stateless codec adapter.
|
/// Creates the stateless codec adapter.
|
||||||
///
|
///
|
||||||
@@ -33,17 +40,7 @@ impl SkiaTextureCodec {
|
|||||||
pub fn decode(&self, mut stream: Box<dyn ReadWrite + Send>) -> Result<ManagedImage, Error> {
|
pub fn decode(&self, mut stream: Box<dyn ReadWrite + Send>) -> Result<ManagedImage, Error> {
|
||||||
#[cfg(feature = "skia")]
|
#[cfg(feature = "skia")]
|
||||||
{
|
{
|
||||||
let mut encoded = Vec::new();
|
let encoded = read_bounded(&mut stream)?;
|
||||||
Read::by_ref(&mut stream)
|
|
||||||
.take((DEFAULT_MAX_ENCODED_BYTES + 1) as u64)
|
|
||||||
.read_to_end(&mut encoded)
|
|
||||||
.map_err(|_| Error::InvalidOperation)?;
|
|
||||||
if encoded.is_empty() {
|
|
||||||
return Err(Error::InvalidOperation);
|
|
||||||
}
|
|
||||||
if encoded.len() > DEFAULT_MAX_ENCODED_BYTES {
|
|
||||||
return Err(Error::Argument);
|
|
||||||
}
|
|
||||||
decode_with_skia(&encoded)
|
decode_with_skia(&encoded)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "skia"))]
|
#[cfg(not(feature = "skia"))]
|
||||||
@@ -65,6 +62,55 @@ impl SkiaTextureCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RustSkiaTextureCodec {
|
||||||
|
/// Creates the stateless pure-Rust codec adapter.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// This fixed compatibility constructor cannot fail.
|
||||||
|
pub const fn new() -> Result<Self, Error> {
|
||||||
|
Ok(Self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes a bounded stream with Rust-only BMP, GIF, ICO, JPEG, PNG,
|
||||||
|
/// WBMP, and WebP codecs.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// With `rust-skia`, returns [`Error::Argument`] for an input or decoded
|
||||||
|
/// canvas above the documented limits and [`Error::InvalidOperation`] for
|
||||||
|
/// malformed or unsupported images. Without the feature it returns
|
||||||
|
/// [`Error::InvalidOperation`].
|
||||||
|
pub fn decode(&self, mut stream: Box<dyn ReadWrite + Send>) -> Result<ManagedImage, Error> {
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
{
|
||||||
|
let encoded = read_bounded(&mut stream)?;
|
||||||
|
decode_with_rust_skia(&encoded)
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "rust-skia"))]
|
||||||
|
{
|
||||||
|
let _ = &mut stream;
|
||||||
|
Err(Error::InvalidOperation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
|
fn read_bounded(stream: &mut (dyn ReadWrite + Send)) -> Result<Vec<u8>, Error> {
|
||||||
|
let mut encoded = Vec::new();
|
||||||
|
stream
|
||||||
|
.take((DEFAULT_MAX_ENCODED_BYTES + 1) as u64)
|
||||||
|
.read_to_end(&mut encoded)
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
if encoded.is_empty() {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
if encoded.len() > DEFAULT_MAX_ENCODED_BYTES {
|
||||||
|
return Err(Error::Argument);
|
||||||
|
}
|
||||||
|
Ok(encoded)
|
||||||
|
}
|
||||||
|
|
||||||
// Keeping the format branches together makes comparison with the pinned C#
|
// Keeping the format branches together makes comparison with the pinned C#
|
||||||
// color switch auditable and prevents subtly different indexing paths.
|
// color switch auditable and prevents subtly different indexing paths.
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
@@ -238,6 +284,404 @@ fn normalize_10bit_alpha(
|
|||||||
(normalize(red), normalize(green), normalize(blue))
|
(normalize(red), normalize(green), normalize(blue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn decode_with_rust_skia(encoded: &[u8]) -> Result<ManagedImage, Error> {
|
||||||
|
use skia_rs_codec::{ImageDecoder, ImageFormat};
|
||||||
|
|
||||||
|
let format = if wbmp_dimensions(encoded).is_ok() {
|
||||||
|
ImageFormat::Wbmp
|
||||||
|
} else {
|
||||||
|
ImageFormat::from_magic(encoded)
|
||||||
|
};
|
||||||
|
if format == ImageFormat::WebP {
|
||||||
|
return decode_webp_with_rust(encoded);
|
||||||
|
}
|
||||||
|
if !matches!(
|
||||||
|
format,
|
||||||
|
ImageFormat::Bmp
|
||||||
|
| ImageFormat::Gif
|
||||||
|
| ImageFormat::Ico
|
||||||
|
| ImageFormat::Jpeg
|
||||||
|
| ImageFormat::Png
|
||||||
|
| ImageFormat::Wbmp
|
||||||
|
) {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (width, height) = match format {
|
||||||
|
ImageFormat::Gif => gif_dimensions(encoded)?,
|
||||||
|
ImageFormat::Ico => ico_dimensions(encoded)?,
|
||||||
|
ImageFormat::Wbmp => wbmp_dimensions(encoded)?,
|
||||||
|
_ => skia_rs_codec::get_image_dimensions(encoded).map_err(|_| Error::InvalidOperation)?,
|
||||||
|
};
|
||||||
|
validate_dimensions(width, height)?;
|
||||||
|
|
||||||
|
let decoded = if format == ImageFormat::Wbmp {
|
||||||
|
skia_rs_codec::WbmpDecoder::new().decode_bytes(encoded)
|
||||||
|
} else {
|
||||||
|
skia_rs_codec::decode_image(encoded)
|
||||||
|
}
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
validate_dimensions(decoded.width(), decoded.height())?;
|
||||||
|
if decoded.width() != width || decoded.height() != height {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let width_usize = usize::try_from(width).map_err(|_| Error::Argument)?;
|
||||||
|
if decoded.row_bytes() != width_usize.checked_mul(4).ok_or(Error::Argument)? {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let source_pixels = decoded.peek_pixels().ok_or(Error::InvalidOperation)?;
|
||||||
|
let grayscale = match format {
|
||||||
|
ImageFormat::Jpeg => jpeg_is_grayscale(encoded)?,
|
||||||
|
ImageFormat::Png => encoded.get(25) == Some(&0),
|
||||||
|
ImageFormat::Wbmp => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
let (row_bytes, color_type, alpha_type, pixels) = if grayscale {
|
||||||
|
let pixel_count = width_usize
|
||||||
|
.checked_mul(usize::try_from(height).map_err(|_| Error::Argument)?)
|
||||||
|
.ok_or(Error::Argument)?;
|
||||||
|
let mut gray = Vec::new();
|
||||||
|
gray.try_reserve_exact(pixel_count)
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
gray.extend(source_pixels.chunks_exact(4).map(|rgba| rgba[0]));
|
||||||
|
if gray.len() != pixel_count {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
(width_usize, SKColorType::Gray8, SKAlphaType::Opaque, gray)
|
||||||
|
} else {
|
||||||
|
let mut rgba = Vec::new();
|
||||||
|
rgba.try_reserve_exact(source_pixels.len())
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
rgba.extend_from_slice(source_pixels);
|
||||||
|
(
|
||||||
|
decoded.row_bytes(),
|
||||||
|
SKColorType::Rgba8888,
|
||||||
|
if decoded.is_opaque() {
|
||||||
|
SKAlphaType::Opaque
|
||||||
|
} else {
|
||||||
|
SKAlphaType::Unpremul
|
||||||
|
},
|
||||||
|
rgba,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let bitmap = SKBitmap::new(width, height, row_bytes, color_type, alpha_type, pixels)?;
|
||||||
|
bitmap_to_managed(&bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn jpeg_is_grayscale(encoded: &[u8]) -> Result<bool, Error> {
|
||||||
|
let mut offset = 2;
|
||||||
|
while offset + 1 < encoded.len() {
|
||||||
|
if encoded[offset] != 0xff {
|
||||||
|
offset += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut marker_offset = offset + 1;
|
||||||
|
while encoded.get(marker_offset) == Some(&0xff) {
|
||||||
|
marker_offset += 1;
|
||||||
|
}
|
||||||
|
let marker = *encoded.get(marker_offset).ok_or(Error::InvalidOperation)?;
|
||||||
|
if marker == 0 || marker == 1 || (0xd0..=0xd9).contains(&marker) {
|
||||||
|
offset = marker_offset + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let length_bytes = encoded
|
||||||
|
.get(marker_offset + 1..marker_offset + 3)
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
let length = usize::from(u16::from_be_bytes(
|
||||||
|
length_bytes
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
));
|
||||||
|
if matches!(
|
||||||
|
marker,
|
||||||
|
0xc0..=0xc3 | 0xc5..=0xc7 | 0xc9..=0xcb | 0xcd..=0xcf
|
||||||
|
) {
|
||||||
|
let components = *encoded
|
||||||
|
.get(marker_offset + 8)
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
return match components {
|
||||||
|
1 => Ok(true),
|
||||||
|
3 => Ok(false),
|
||||||
|
_ => Err(Error::InvalidOperation),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if length < 2 {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
offset = marker_offset
|
||||||
|
.checked_add(1)
|
||||||
|
.and_then(|offset| offset.checked_add(length))
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
}
|
||||||
|
Err(Error::InvalidOperation)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn gif_dimensions(encoded: &[u8]) -> Result<(i32, i32), Error> {
|
||||||
|
if encoded.len() < 13 || !(encoded.starts_with(b"GIF87a") || encoded.starts_with(b"GIF89a")) {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let canvas = (
|
||||||
|
i32::from(u16::from_le_bytes([encoded[6], encoded[7]])),
|
||||||
|
i32::from(u16::from_le_bytes([encoded[8], encoded[9]])),
|
||||||
|
);
|
||||||
|
validate_dimensions(canvas.0, canvas.1)?;
|
||||||
|
|
||||||
|
let global_table_bytes = if encoded[10] & 0x80 == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
3_usize
|
||||||
|
.checked_mul(1_usize << (usize::from(encoded[10] & 0x07) + 1))
|
||||||
|
.ok_or(Error::InvalidOperation)?
|
||||||
|
};
|
||||||
|
let mut offset = 13_usize
|
||||||
|
.checked_add(global_table_bytes)
|
||||||
|
.filter(|offset| *offset <= encoded.len())
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
loop {
|
||||||
|
let marker = *encoded.get(offset).ok_or(Error::InvalidOperation)?;
|
||||||
|
offset += 1;
|
||||||
|
match marker {
|
||||||
|
0x2c => {
|
||||||
|
let end = offset.checked_add(9).ok_or(Error::InvalidOperation)?;
|
||||||
|
let descriptor = encoded.get(offset..end).ok_or(Error::InvalidOperation)?;
|
||||||
|
let frame_width = i32::from(u16::from_le_bytes([descriptor[4], descriptor[5]]));
|
||||||
|
let frame_height = i32::from(u16::from_le_bytes([descriptor[6], descriptor[7]]));
|
||||||
|
validate_dimensions(frame_width, frame_height)?;
|
||||||
|
return Ok(canvas);
|
||||||
|
}
|
||||||
|
0x21 => {
|
||||||
|
offset = offset.checked_add(1).ok_or(Error::InvalidOperation)?;
|
||||||
|
loop {
|
||||||
|
let length = *encoded.get(offset).ok_or(Error::InvalidOperation)?;
|
||||||
|
offset += 1;
|
||||||
|
if length == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset = offset
|
||||||
|
.checked_add(usize::from(length))
|
||||||
|
.filter(|offset| *offset <= encoded.len())
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(Error::InvalidOperation),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn wbmp_dimensions(encoded: &[u8]) -> Result<(i32, i32), Error> {
|
||||||
|
if encoded.get(..2) != Some(&[0, 0]) {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let mut offset = 2;
|
||||||
|
let width =
|
||||||
|
i32::try_from(read_wbmp_integer(encoded, &mut offset)?).map_err(|_| Error::Argument)?;
|
||||||
|
let height =
|
||||||
|
i32::try_from(read_wbmp_integer(encoded, &mut offset)?).map_err(|_| Error::Argument)?;
|
||||||
|
validate_dimensions(width, height)?;
|
||||||
|
Ok((width, height))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn read_wbmp_integer(encoded: &[u8], offset: &mut usize) -> Result<u32, Error> {
|
||||||
|
let mut value = 0_u32;
|
||||||
|
for _ in 0..5 {
|
||||||
|
let byte = *encoded.get(*offset).ok_or(Error::InvalidOperation)?;
|
||||||
|
*offset += 1;
|
||||||
|
value = value
|
||||||
|
.checked_shl(7)
|
||||||
|
.and_then(|value| value.checked_add(u32::from(byte & 0x7f)))
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
if byte & 0x80 == 0 {
|
||||||
|
return Ok(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(Error::InvalidOperation)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn ico_dimensions(encoded: &[u8]) -> Result<(i32, i32), Error> {
|
||||||
|
if encoded.len() < 6 || encoded.get(..4) != Some(&[0, 0, 1, 0]) {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let count = usize::from(u16::from_le_bytes([encoded[4], encoded[5]]));
|
||||||
|
let mut best: Option<(u32, usize, usize)> = None;
|
||||||
|
for index in 0..count {
|
||||||
|
let offset = 6_usize
|
||||||
|
.checked_add(index.checked_mul(16).ok_or(Error::InvalidOperation)?)
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
let end = offset.checked_add(16).ok_or(Error::InvalidOperation)?;
|
||||||
|
let entry = encoded.get(offset..end).ok_or(Error::InvalidOperation)?;
|
||||||
|
let width = if entry[0] == 0 {
|
||||||
|
256
|
||||||
|
} else {
|
||||||
|
u32::from(entry[0])
|
||||||
|
};
|
||||||
|
let height = if entry[1] == 0 {
|
||||||
|
256
|
||||||
|
} else {
|
||||||
|
u32::from(entry[1])
|
||||||
|
};
|
||||||
|
let area = width.checked_mul(height).ok_or(Error::Argument)?;
|
||||||
|
let length = usize::try_from(u32::from_le_bytes(
|
||||||
|
entry[8..12]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
))
|
||||||
|
.map_err(|_| Error::Argument)?;
|
||||||
|
let image_offset = usize::try_from(u32::from_le_bytes(
|
||||||
|
entry[12..16]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
))
|
||||||
|
.map_err(|_| Error::Argument)?;
|
||||||
|
if best.is_none_or(|(best_area, _, _)| area > best_area) {
|
||||||
|
best = Some((area, image_offset, length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (_, offset, length) = best.ok_or(Error::InvalidOperation)?;
|
||||||
|
let end = offset.checked_add(length).ok_or(Error::Argument)?;
|
||||||
|
let image = encoded
|
||||||
|
.get(offset..end)
|
||||||
|
.filter(|image| !image.is_empty())
|
||||||
|
.ok_or(Error::InvalidOperation)?;
|
||||||
|
if image.starts_with(&[0x89, b'P', b'N', b'G']) {
|
||||||
|
return skia_rs_codec::get_image_dimensions(image).map_err(|_| Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
if image.len() < 40 {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let header_size = u32::from_le_bytes(
|
||||||
|
image[0..4]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
);
|
||||||
|
if header_size < 40 {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
let width = i32::from_le_bytes(
|
||||||
|
image[4..8]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
);
|
||||||
|
let stored_height = i32::from_le_bytes(
|
||||||
|
image[8..12]
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| Error::InvalidOperation)?,
|
||||||
|
);
|
||||||
|
if stored_height <= 0 || stored_height % 2 != 0 {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
Ok((width, stored_height / 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn validate_dimensions(width: i32, height: i32) -> Result<(), Error> {
|
||||||
|
let width = usize::try_from(width).map_err(|_| Error::Argument)?;
|
||||||
|
let height = usize::try_from(height).map_err(|_| Error::Argument)?;
|
||||||
|
width
|
||||||
|
.checked_mul(height)
|
||||||
|
.filter(|pixels| *pixels > 0 && *pixels <= DEFAULT_MAX_PIXELS)
|
||||||
|
.map(|_| ())
|
||||||
|
.ok_or(Error::Argument)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn decode_webp_with_rust(encoded: &[u8]) -> Result<ManagedImage, Error> {
|
||||||
|
use std::io::{BufReader, Cursor};
|
||||||
|
|
||||||
|
let reader = BufReader::new(Cursor::new(encoded));
|
||||||
|
let mut decoder = image_webp::WebPDecoder::new(reader).map_err(|_| Error::InvalidOperation)?;
|
||||||
|
let (width, height) = decoder.dimensions();
|
||||||
|
let animated = decoder.is_animated();
|
||||||
|
let width_i32 = i32::try_from(width).map_err(|_| Error::Argument)?;
|
||||||
|
let height_i32 = i32::try_from(height).map_err(|_| Error::Argument)?;
|
||||||
|
validate_dimensions(width_i32, height_i32)?;
|
||||||
|
decoder.set_memory_limit(DEFAULT_MAX_PIXELS * 16);
|
||||||
|
|
||||||
|
let output_size = decoder.output_buffer_size().ok_or(Error::Argument)?;
|
||||||
|
if output_size > DEFAULT_MAX_PIXELS * 4 {
|
||||||
|
return Err(Error::Argument);
|
||||||
|
}
|
||||||
|
let mut packed_pixels = Vec::new();
|
||||||
|
packed_pixels
|
||||||
|
.try_reserve_exact(output_size)
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
packed_pixels.resize(output_size, 0);
|
||||||
|
decoder
|
||||||
|
.read_image(&mut packed_pixels)
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
|
||||||
|
let has_alpha = decoder.has_alpha();
|
||||||
|
// image-webp 0.2 uses a divide-by-256 blend fast path for animated
|
||||||
|
// canvases. Its fully opaque nonzero samples are consequently one below
|
||||||
|
// Skia/libwebp's divide-by-255 result. Correct that bounded first-frame
|
||||||
|
// canvas here; partially transparent samples already use the same rounding
|
||||||
|
// as the compatibility backend.
|
||||||
|
if animated {
|
||||||
|
if has_alpha {
|
||||||
|
for rgba in packed_pixels.chunks_exact_mut(4) {
|
||||||
|
if rgba[3] == u8::MAX {
|
||||||
|
for channel in &mut rgba[..3] {
|
||||||
|
if *channel != 0 {
|
||||||
|
*channel = channel.saturating_add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for channel in &mut packed_pixels {
|
||||||
|
if *channel != 0 {
|
||||||
|
*channel = channel.saturating_add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let pixels = if has_alpha {
|
||||||
|
packed_pixels
|
||||||
|
} else {
|
||||||
|
let pixel_count = usize::try_from(width)
|
||||||
|
.ok()
|
||||||
|
.and_then(|width| {
|
||||||
|
usize::try_from(height)
|
||||||
|
.ok()
|
||||||
|
.and_then(|height| width.checked_mul(height))
|
||||||
|
})
|
||||||
|
.ok_or(Error::Argument)?;
|
||||||
|
let rgba_size = pixel_count.checked_mul(4).ok_or(Error::Argument)?;
|
||||||
|
let mut rgba = Vec::new();
|
||||||
|
rgba.try_reserve_exact(rgba_size)
|
||||||
|
.map_err(|_| Error::InvalidOperation)?;
|
||||||
|
for rgb in packed_pixels.chunks_exact(3) {
|
||||||
|
rgba.extend_from_slice(&[rgb[0], rgb[1], rgb[2], u8::MAX]);
|
||||||
|
}
|
||||||
|
if rgba.len() != rgba_size {
|
||||||
|
return Err(Error::InvalidOperation);
|
||||||
|
}
|
||||||
|
rgba
|
||||||
|
};
|
||||||
|
let row_bytes = usize::try_from(width)
|
||||||
|
.map_err(|_| Error::Argument)?
|
||||||
|
.checked_mul(4)
|
||||||
|
.ok_or(Error::Argument)?;
|
||||||
|
let bitmap = SKBitmap::new(
|
||||||
|
width_i32,
|
||||||
|
height_i32,
|
||||||
|
row_bytes,
|
||||||
|
SKColorType::Rgba8888,
|
||||||
|
if has_alpha {
|
||||||
|
SKAlphaType::Unpremul
|
||||||
|
} else {
|
||||||
|
SKAlphaType::Opaque
|
||||||
|
},
|
||||||
|
pixels,
|
||||||
|
)?;
|
||||||
|
bitmap_to_managed(&bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "skia")]
|
#[cfg(feature = "skia")]
|
||||||
fn decode_with_skia(encoded: &[u8]) -> Result<ManagedImage, Error> {
|
fn decode_with_skia(encoded: &[u8]) -> Result<ManagedImage, Error> {
|
||||||
use skia_safe::Data;
|
use skia_safe::Data;
|
||||||
@@ -528,6 +972,394 @@ mod tests {
|
|||||||
SkiaTextureCodec.decode(Box::new(std::io::Cursor::new(Vec::new()))),
|
SkiaTextureCodec.decode(Box::new(std::io::Cursor::new(Vec::new()))),
|
||||||
Err(Error::InvalidOperation)
|
Err(Error::InvalidOperation)
|
||||||
);
|
);
|
||||||
|
#[cfg(not(feature = "rust-skia"))]
|
||||||
|
assert_eq!(
|
||||||
|
RustSkiaTextureCodec.decode(Box::new(std::io::Cursor::new(Vec::new()))),
|
||||||
|
Err(Error::InvalidOperation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
|
fn hex_fixture(source: &str) -> Vec<u8> {
|
||||||
|
let digits: Vec<_> = source.bytes().filter(u8::is_ascii_hexdigit).collect();
|
||||||
|
assert_eq!(digits.len() % 2, 0, "fixture contains a partial byte");
|
||||||
|
digits
|
||||||
|
.chunks_exact(2)
|
||||||
|
.map(|pair| {
|
||||||
|
let high = (pair[0] as char).to_digit(16).expect("hex digit");
|
||||||
|
let low = (pair[1] as char).to_digit(16).expect("hex digit");
|
||||||
|
u8::try_from(high * 16 + low).expect("hex byte")
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
fn rust_decode(encoded: Vec<u8>) -> Result<ManagedImage, Error> {
|
||||||
|
RustSkiaTextureCodec.decode(Box::new(std::io::Cursor::new(encoded)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
|
fn checked_format_matrix() -> [(&'static str, &'static str, (i32, i32)); 19] {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"BMP 16-bit RGB555",
|
||||||
|
include_str!("../tests/fixtures/rgb555.bmp.hex"),
|
||||||
|
(2, 1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"BMP 24-bit bottom-up",
|
||||||
|
include_str!("../tests/fixtures/bottom-up.bmp.hex"),
|
||||||
|
(8, 8),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"BMP 32-bit BGRX",
|
||||||
|
include_str!("../tests/fixtures/bgrx32.bmp.hex"),
|
||||||
|
(2, 1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"GIF palette and frame offset",
|
||||||
|
include_str!("../tests/fixtures/palette-offset.gif.hex"),
|
||||||
|
(4, 2),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ICO largest entry",
|
||||||
|
include_str!("../tests/fixtures/multi.ico.hex"),
|
||||||
|
(2, 2),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JPEG baseline RGB",
|
||||||
|
include_str!("../tests/fixtures/baseline.jpg.hex"),
|
||||||
|
(8, 8),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"JPEG progressive grayscale",
|
||||||
|
include_str!("../tests/fixtures/progressive.jpg.hex"),
|
||||||
|
(128, 128),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG grayscale",
|
||||||
|
include_str!("../tests/fixtures/gray.png.hex"),
|
||||||
|
(32, 32),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG grayscale alpha",
|
||||||
|
include_str!("../tests/fixtures/gray-alpha.png.hex"),
|
||||||
|
(32, 32),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG RGB",
|
||||||
|
include_str!("../tests/fixtures/rgb.png.hex"),
|
||||||
|
(32, 32),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG RGBA",
|
||||||
|
include_str!("../tests/fixtures/rgba.png.hex"),
|
||||||
|
(32, 32),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG straight alpha",
|
||||||
|
include_str!("../tests/fixtures/straight-alpha.png.hex"),
|
||||||
|
(1, 1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"PNG interlaced palette",
|
||||||
|
include_str!("../tests/fixtures/interlaced-palette.png.hex"),
|
||||||
|
(32, 32),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WBMP multibyte width",
|
||||||
|
include_str!("../tests/fixtures/multibyte.wbmp.hex"),
|
||||||
|
(130, 1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WBMP minimum-length image",
|
||||||
|
include_str!("../tests/fixtures/small.wbmp.hex"),
|
||||||
|
(2, 2),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WebP lossless RGB",
|
||||||
|
include_str!("../tests/fixtures/rgb-lossless.webp.hex"),
|
||||||
|
(2, 2),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WebP lossless alpha",
|
||||||
|
include_str!("../tests/fixtures/alpha.webp.hex"),
|
||||||
|
(1, 1),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WebP lossy",
|
||||||
|
include_str!("../tests/fixtures/lossy-red.webp.hex"),
|
||||||
|
(8, 8),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"WebP animated first frame",
|
||||||
|
include_str!("../tests/fixtures/animated.webp.hex"),
|
||||||
|
(11, 29),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "rust-skia", feature = "skia"))]
|
||||||
|
fn assert_checked_format_matrix(codec: &dyn libremetaverse_imaging::ITextureCodec) {
|
||||||
|
for (name, fixture, dimensions) in checked_format_matrix() {
|
||||||
|
let image = codec
|
||||||
|
.decode(Box::new(std::io::Cursor::new(hex_fixture(fixture))))
|
||||||
|
.unwrap_or_else(|error| panic!("{name} failed to decode: {error:?}"));
|
||||||
|
assert_eq!((image.width, image.height), dimensions, "{name}");
|
||||||
|
assert_eq!(
|
||||||
|
image.channels,
|
||||||
|
if matches!(
|
||||||
|
name,
|
||||||
|
"JPEG progressive grayscale"
|
||||||
|
| "PNG grayscale"
|
||||||
|
| "WBMP multibyte width"
|
||||||
|
| "WBMP minimum-length image"
|
||||||
|
) {
|
||||||
|
ManagedImageImageChannels::GRAY
|
||||||
|
} else {
|
||||||
|
ManagedImageImageChannels::COLOR | ManagedImageImageChannels::ALPHA
|
||||||
|
},
|
||||||
|
"{name}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
#[test]
|
||||||
|
fn rust_feature_decodes_the_checked_format_matrix() {
|
||||||
|
assert_checked_format_matrix(&RustSkiaTextureCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "skia")]
|
||||||
|
#[test]
|
||||||
|
fn native_feature_decodes_the_checked_format_matrix() {
|
||||||
|
assert_checked_format_matrix(&SkiaTextureCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rust-skia", feature = "skia"))]
|
||||||
|
#[test]
|
||||||
|
fn native_and_rust_backends_match_the_shared_contract_matrix() {
|
||||||
|
fn assert_plane(name: &str, plane: &str, native: &[u8], rust: &[u8], tolerance: u8) {
|
||||||
|
assert_eq!(native.len(), rust.len(), "{name} {plane} length");
|
||||||
|
for (index, (&native, &rust)) in native.iter().zip(rust).enumerate() {
|
||||||
|
assert!(
|
||||||
|
native.abs_diff(rust) <= tolerance,
|
||||||
|
"{name} {plane}[{index}]: native={native}, rust={rust}, tolerance={tolerance}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, fixture, _) in checked_format_matrix() {
|
||||||
|
let bytes = hex_fixture(fixture);
|
||||||
|
let native = SkiaTextureCodec
|
||||||
|
.decode(Box::new(std::io::Cursor::new(bytes.clone())))
|
||||||
|
.unwrap_or_else(|error| panic!("native {name}: {error:?}"));
|
||||||
|
let rust = RustSkiaTextureCodec
|
||||||
|
.decode(Box::new(std::io::Cursor::new(bytes)))
|
||||||
|
.unwrap_or_else(|error| panic!("Rust {name}: {error:?}"));
|
||||||
|
assert_eq!(native.width, rust.width, "{name} width");
|
||||||
|
assert_eq!(native.height, rust.height, "{name} height");
|
||||||
|
assert_eq!(native.channels, rust.channels, "{name} channels");
|
||||||
|
let tolerance = if name.starts_with("JPEG") {
|
||||||
|
8
|
||||||
|
} else if name == "WebP lossy" {
|
||||||
|
10
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
assert_plane(name, "red", &native.red, &rust.red, tolerance);
|
||||||
|
assert_plane(name, "green", &native.green, &rust.green, tolerance);
|
||||||
|
assert_plane(name, "blue", &native.blue, &rust.blue, tolerance);
|
||||||
|
assert_plane(name, "alpha", &native.alpha, &rust.alpha, tolerance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
#[test]
|
||||||
|
fn rust_feature_preserves_canvas_orientation_selection_and_alpha() {
|
||||||
|
for fixture in [
|
||||||
|
include_str!("../tests/fixtures/two-by-two-bottom-up.bmp.hex"),
|
||||||
|
include_str!("../tests/fixtures/two-by-two-top-down.bmp.hex"),
|
||||||
|
] {
|
||||||
|
let bitmap = rust_decode(hex_fixture(fixture)).expect("oriented BMP");
|
||||||
|
assert_eq!(bitmap.red, [255, 0, 0, 255]);
|
||||||
|
assert_eq!(bitmap.green, [0, 255, 0, 255]);
|
||||||
|
assert_eq!(bitmap.blue, [0, 0, 255, 255]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let gif = rust_decode(hex_fixture(include_str!(
|
||||||
|
"../tests/fixtures/palette-offset.gif.hex"
|
||||||
|
)))
|
||||||
|
.expect("GIF logical canvas");
|
||||||
|
assert_eq!((gif.width, gif.height), (4, 2));
|
||||||
|
|
||||||
|
let icon = rust_decode(hex_fixture(include_str!("../tests/fixtures/multi.ico.hex")))
|
||||||
|
.expect("largest ICO entry");
|
||||||
|
assert_eq!(icon.red, [255, 0, 0, 255]);
|
||||||
|
assert_eq!(icon.green, [0, 255, 0, 255]);
|
||||||
|
assert_eq!(icon.blue, [0, 0, 255, 255]);
|
||||||
|
|
||||||
|
let alpha = rust_decode(hex_fixture(include_str!(
|
||||||
|
"../tests/fixtures/alpha.webp.hex"
|
||||||
|
)))
|
||||||
|
.expect("alpha WebP");
|
||||||
|
assert_eq!(
|
||||||
|
(alpha.red[0], alpha.green[0], alpha.blue[0]),
|
||||||
|
(255, 255, 255)
|
||||||
|
);
|
||||||
|
assert!((127..=128).contains(&alpha.alpha[0]));
|
||||||
|
|
||||||
|
let lossy = rust_decode(hex_fixture(include_str!(
|
||||||
|
"../tests/fixtures/lossy-red.webp.hex"
|
||||||
|
)))
|
||||||
|
.expect("lossy WebP");
|
||||||
|
assert!(lossy.red.iter().all(|red| *red >= 245));
|
||||||
|
assert!(lossy.green.iter().all(|green| *green <= 10));
|
||||||
|
assert!(lossy.blue.iter().all(|blue| *blue <= 10));
|
||||||
|
assert!(lossy.alpha.iter().all(|alpha| *alpha == u8::MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
#[test]
|
||||||
|
fn rust_feature_rejects_invalid_truncated_and_oversized_input_without_panicking() {
|
||||||
|
for malformed in [Vec::new(), b"not an image".to_vec(), b"GIF89a".to_vec()] {
|
||||||
|
let result =
|
||||||
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| rust_decode(malformed)));
|
||||||
|
assert!(result.is_ok(), "malformed input panicked");
|
||||||
|
assert_eq!(result.expect("checked above"), Err(Error::InvalidOperation));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pixel_bomb =
|
||||||
|
hex_fixture(include_str!("../tests/fixtures/interlaced-palette.png.hex"));
|
||||||
|
pixel_bomb[16..20].copy_from_slice(&4097_u32.to_be_bytes());
|
||||||
|
pixel_bomb[20..24].copy_from_slice(&4097_u32.to_be_bytes());
|
||||||
|
assert_eq!(rust_decode(pixel_bomb), Err(Error::Argument));
|
||||||
|
|
||||||
|
let mut gif_frame_bomb =
|
||||||
|
hex_fixture(include_str!("../tests/fixtures/palette-offset.gif.hex"));
|
||||||
|
let descriptor = gif_frame_bomb[109..]
|
||||||
|
.iter()
|
||||||
|
.position(|byte| *byte == 0x2c)
|
||||||
|
.map(|offset| offset + 109)
|
||||||
|
.expect("first GIF image descriptor");
|
||||||
|
gif_frame_bomb[descriptor + 5..descriptor + 7].copy_from_slice(&u16::MAX.to_le_bytes());
|
||||||
|
gif_frame_bomb[descriptor + 7..descriptor + 9].copy_from_slice(&u16::MAX.to_le_bytes());
|
||||||
|
assert_eq!(rust_decode(gif_frame_bomb), Err(Error::Argument));
|
||||||
|
|
||||||
|
let mut malformed_gif_palette =
|
||||||
|
hex_fixture(include_str!("../tests/fixtures/palette-offset.gif.hex"));
|
||||||
|
// Advertise a 256-entry global palette while retaining the fixture's
|
||||||
|
// much smaller checked table. Preflight must reject the missing table
|
||||||
|
// before the decoder can allocate or index palette storage.
|
||||||
|
malformed_gif_palette[10] = (malformed_gif_palette[10] & 0xf8) | 0x07;
|
||||||
|
assert_eq!(
|
||||||
|
rust_decode(malformed_gif_palette),
|
||||||
|
Err(Error::InvalidOperation)
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut icon_embedded_bomb = hex_fixture(include_str!("../tests/fixtures/multi.ico.hex"));
|
||||||
|
icon_embedded_bomb[86..90].copy_from_slice(&4097_i32.to_le_bytes());
|
||||||
|
icon_embedded_bomb[90..94].copy_from_slice(&8194_i32.to_le_bytes());
|
||||||
|
assert_eq!(rust_decode(icon_embedded_bomb), Err(Error::Argument));
|
||||||
|
|
||||||
|
let over_limit = vec![0_u8; DEFAULT_MAX_ENCODED_BYTES + 1];
|
||||||
|
assert_eq!(rust_decode(over_limit), Err(Error::Argument));
|
||||||
|
|
||||||
|
for fixture in [
|
||||||
|
include_str!("../tests/fixtures/bottom-up.bmp.hex"),
|
||||||
|
include_str!("../tests/fixtures/palette-offset.gif.hex"),
|
||||||
|
include_str!("../tests/fixtures/multi.ico.hex"),
|
||||||
|
include_str!("../tests/fixtures/interlaced-palette.png.hex"),
|
||||||
|
include_str!("../tests/fixtures/alpha.webp.hex"),
|
||||||
|
] {
|
||||||
|
let mut bytes = hex_fixture(fixture);
|
||||||
|
bytes.truncate(bytes.len() / 2);
|
||||||
|
let result =
|
||||||
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| rust_decode(bytes)));
|
||||||
|
assert!(result.is_ok(), "truncated input panicked");
|
||||||
|
assert!(result.expect("checked above").is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
struct DropStream {
|
||||||
|
cursor: std::io::Cursor<Vec<u8>>,
|
||||||
|
drops: std::sync::Arc<std::sync::atomic::AtomicUsize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
impl std::io::Read for DropStream {
|
||||||
|
fn read(&mut self, buffer: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
std::io::Read::read(&mut self.cursor, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
impl std::io::Write for DropStream {
|
||||||
|
fn write(&mut self, buffer: &[u8]) -> std::io::Result<usize> {
|
||||||
|
std::io::Write::write(&mut self.cursor, buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
impl std::io::Seek for DropStream {
|
||||||
|
fn seek(&mut self, position: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||||
|
std::io::Seek::seek(&mut self.cursor, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
impl Drop for DropStream {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.drops.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust-skia")]
|
||||||
|
#[test]
|
||||||
|
fn rust_feature_is_thread_safe_across_repeated_decode_and_drop() {
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
fn assert_texture_codec<T: libremetaverse_imaging::ITextureCodec + Send + Sync>() {}
|
||||||
|
assert_texture_codec::<RustSkiaTextureCodec>();
|
||||||
|
|
||||||
|
let codec = Arc::new(RustSkiaTextureCodec);
|
||||||
|
let png = Arc::new(hex_fixture(include_str!(
|
||||||
|
"../tests/fixtures/interlaced-palette.png.hex"
|
||||||
|
)));
|
||||||
|
let mut workers = Vec::new();
|
||||||
|
for _ in 0..8 {
|
||||||
|
let codec = Arc::clone(&codec);
|
||||||
|
let png = Arc::clone(&png);
|
||||||
|
workers.push(std::thread::spawn(move || {
|
||||||
|
for _ in 0..16 {
|
||||||
|
let image = codec
|
||||||
|
.decode(Box::new(std::io::Cursor::new((*png).clone())))
|
||||||
|
.expect("concurrent PNG decode");
|
||||||
|
assert_eq!((image.width, image.height), (32, 32));
|
||||||
|
let repeated = codec
|
||||||
|
.decode(Box::new(std::io::Cursor::new((*png).clone())))
|
||||||
|
.expect("repeated concurrent PNG decode");
|
||||||
|
assert_eq!(image, repeated);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
for worker in workers {
|
||||||
|
worker.join().expect("decoder worker did not panic");
|
||||||
|
}
|
||||||
|
|
||||||
|
let drops = Arc::new(AtomicUsize::new(0));
|
||||||
|
let stream = DropStream {
|
||||||
|
cursor: std::io::Cursor::new((*png).clone()),
|
||||||
|
drops: Arc::clone(&drops),
|
||||||
|
};
|
||||||
|
codec.decode(Box::new(stream)).expect("drop-probe decode");
|
||||||
|
assert_eq!(drops.load(Ordering::SeqCst), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "skia")]
|
#[cfg(feature = "skia")]
|
||||||
|
|||||||
29
crates/libremetaverse-imaging-skia/tests/fixtures/README.md
vendored
Normal file
29
crates/libremetaverse-imaging-skia/tests/fixtures/README.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Rust codec fixtures
|
||||||
|
|
||||||
|
The tests decode these hexadecimal files into their exact checked-in bytes; no
|
||||||
|
image is generated while tests run. Unless noted below, fixtures come from the
|
||||||
|
BSD-3-Clause Skia test resources vendored by `skia-bindings 0.99.0`.
|
||||||
|
|
||||||
|
| Fixture | SHA-256 |
|
||||||
|
| --- | --- |
|
||||||
|
| `alpha.webp` | `8b09993d8ffc9a9ec4e7f5f26a1c126cf265c37b0d63c0c5be2506e20dbc6fea` |
|
||||||
|
| `animated.webp` | `292753f066add623af1e30bbeeca58f15b3d6d1052e12b13e30f21f8d3c14505` |
|
||||||
|
| `baseline.jpg` | `4e45048dbe3078943eb364221a9757df9b9845b80e795ccdc944f1c18b5e221b` |
|
||||||
|
| `bottom-up.bmp` | `d9cc5fff9e8e351727ad4519236ae46eaf37f8007dad5cdb8619fcd67ec68903` |
|
||||||
|
| `gray-alpha.png` | `377a67510b4ccc74cdcce14847b02035e75ccab36e9d8e00586c4c24d1ae385a` |
|
||||||
|
| `gray.png` | `85b19fcda452d6cbf02f570c353cfa9e47c29237f2fc8f0114deb6cd0b23f97a` |
|
||||||
|
| `interlaced-palette.png` | `6283a61b1f7344c0cfa741076d6aed4a16a6bc5582e81db8dd7374a34230b0df` |
|
||||||
|
| `palette-offset.gif` | `32d3409a79b75614ef385354d54f148f08856f8e9ce0d55054582ff7f40f4461` |
|
||||||
|
| `progressive.jpg` | `d07a9815dc792543c16b796ec7729c19d6a29e7d9b4d0bbab50f4ef210be7767` |
|
||||||
|
| `rgb.png` | `ecea1ef4a001a999ce9b82d18abf47401eb92998708b306b6c9a8ac3a6a9a2c8` |
|
||||||
|
| `rgba.png` | `756a03364c02e3c9f85d6f4029eb3cef2488c081dc537d46e102bebcb9e02732` |
|
||||||
|
| `straight-alpha.png` | `5a647404fa5289da777b1bb9e1dcfe20027262f992a214f38efaecc3da0e08a4` |
|
||||||
|
|
||||||
|
`lossy-red.webp` was produced once with FFmpeg 5.1.8/libwebp from a solid
|
||||||
|
8x8 red source (`-c:v libwebp -lossless 0 -quality 80`) and has SHA-256
|
||||||
|
`7e3aaf1a442b6e69f7706ee5afe0aeacb2d096e384dbb63e792421fe2449cfe8`.
|
||||||
|
|
||||||
|
The remaining tiny BMP, ICO, WBMP, and lossless RGB WebP files are original
|
||||||
|
MetaCrate byte-level fixtures. Their reviewed bytes are intentionally readable
|
||||||
|
in the `.hex` files and exercise header fields, row layout, masks, multi-byte
|
||||||
|
integers, and multi-entry selection directly.
|
||||||
3
crates/libremetaverse-imaging-skia/tests/fixtures/alpha.webp.hex
vendored
Normal file
3
crates/libremetaverse-imaging-skia/tests/fixtures/alpha.webp.hex
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
524946461e000000574542505650384c110000002f0000001007d0fffef7
|
||||||
|
bf7f8188e87f0000
|
||||||
|
|
||||||
12
crates/libremetaverse-imaging-skia/tests/fixtures/animated.webp.hex
vendored
Normal file
12
crates/libremetaverse-imaging-skia/tests/fixtures/animated.webp.hex
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
524946464c01000057454250565038580a000000120000000a00001c0000
|
||||||
|
414e494d060000000000ffff0000414e4d465a0000000000000000000a00
|
||||||
|
001c0000e80300005650384c420000002f0a0007001720164ce6ff849cc6
|
||||||
|
388ee3fc078e0645b1ad54573b50821444f0db8728aec9f9562688e8bf80
|
||||||
|
a0c8013bd09c2c5e759505ce8f25232ee33615170c0d414e4d465a000000
|
||||||
|
010000050000060000100000f40100005650384c420000002f0600040017
|
||||||
|
201048525e647e814092f222330b049298079979fe037f15288a6ca749a3
|
||||||
|
de31819aee2fc70c32898988fe4f008092d5d79d5525f8079e709b3b6120
|
||||||
|
414e4d465c0000000100000100000600000f0000e80300005650384c4400
|
||||||
|
00002f06c0030017201048621e647e814092f222330b049298079979fe03
|
||||||
|
7f15286a1bc9b9defe4362d05ce5b7cfd5c23c1411fd4f093a8c46a30e09
|
||||||
|
ee4f7ff3c3c3c3cdd303
|
||||||
11
crates/libremetaverse-imaging-skia/tests/fixtures/baseline.jpg.hex
vendored
Normal file
11
crates/libremetaverse-imaging-skia/tests/fixtures/baseline.jpg.hex
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
ffd8ffe000104a46494600010101004800480000ffdb004300100b0c0e0c
|
||||||
|
0a100e0d0e1211101318281a181616183123251d283a333d3c3933383740
|
||||||
|
485c4e404457453738506d51575f626768673e4d71797064785c656763ff
|
||||||
|
db0043011112121815182f1a1a2f63423842636363636363636363636363
|
||||||
|
636363636363636363636363636363636363636363636363636363636363
|
||||||
|
6363636363636363ffc00011080008000803012200021101031101ffc400
|
||||||
|
1500010100000000000000000000000000000003ffc4001e100002010403
|
||||||
|
01000000000000000000000102000311213112224171ffc4001501010100
|
||||||
|
000000000000000000000000000304ffc4001a1101000203010000000000
|
||||||
|
00000000000001000203213141ffda000c03010002110311003f009d4e6a
|
||||||
|
8c15b354b2d455eda6b922c32367dd7db2222d6c9a2558c7c5393fffd9
|
||||||
2
crates/libremetaverse-imaging-skia/tests/fixtures/bgrx32.bmp.hex
vendored
Normal file
2
crates/libremetaverse-imaging-skia/tests/fixtures/bgrx32.bmp.hex
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
424d3e000000000000003600000028000000020000000100000001002000000000000800000000000000000000000000000000000000
|
||||||
|
0000ff0000ff0000
|
||||||
10
crates/libremetaverse-imaging-skia/tests/fixtures/bottom-up.bmp.hex
vendored
Normal file
10
crates/libremetaverse-imaging-skia/tests/fixtures/bottom-up.bmp.hex
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
424df6000000000000003600000028000000080000000800000001001800
|
||||||
|
00000000c0000000130b0000130b000000000000000000002272b0f8232e
|
||||||
|
d989f03857b32260a8fe403371fe95df716a63fea76b954ce022bce472b2
|
||||||
|
4a9f121345e342373d0a19bd98ac6f271d9411e45f83b2fb996ed8629116
|
||||||
|
8c1271b4ca39f93d27831ab4c312f867abcc184203a7b97d481082b44afe
|
||||||
|
5221c5d6cc78abb4dc7dd209f300ca475d60b26f44466e5742f73ba8028f
|
||||||
|
df09557e02c78aaa24966c888154628936400ea6bdb61dc088d62bd46293
|
||||||
|
b241c6decea5ba6e60f34b8f70a5bb5d5f39395ce266761927ba3cb0fcde
|
||||||
|
7438c19300fa
|
||||||
|
|
||||||
5
crates/libremetaverse-imaging-skia/tests/fixtures/gray-alpha.png.hex
vendored
Normal file
5
crates/libremetaverse-imaging-skia/tests/fixtures/gray-alpha.png.hex
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
89504e470d0a1a0a0000000d4948445200000020000000200804000000d9
|
||||||
|
73b27f0000000467414d41000186a031e8965f0000003549444154488963
|
||||||
|
fccfc0c001859c683431229c2cdf1928032c3f86be01a361301a06543160
|
||||||
|
341047c3802a068c06e2681850c30000df2a207da0bf7158000000004945
|
||||||
|
4e44ae426082
|
||||||
5
crates/libremetaverse-imaging-skia/tests/fixtures/gray.png.hex
vendored
Normal file
5
crates/libremetaverse-imaging-skia/tests/fixtures/gray.png.hex
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
89504e470d0a1a0a0000000d494844520000002000000020080000000056
|
||||||
|
1125280000000467414d41000186a031e8965f0000004149444154388d63
|
||||||
|
646024001408c8b30c05058c0f0829f8f71f3f6079301c1430ca11906764
|
||||||
|
a2795c0c06058c8ff0cafeffcff887e67131181430cae0956564040050e5
|
||||||
|
fe7171a90b240000000049454e44ae426082
|
||||||
5
crates/libremetaverse-imaging-skia/tests/fixtures/interlaced-palette.png.hex
vendored
Normal file
5
crates/libremetaverse-imaging-skia/tests/fixtures/interlaced-palette.png.hex
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
89504e470d0a1a0a0000000d49484452000000200000002001030000013e
|
||||||
|
b3d82100000006504c5445eeff222266ff6c1ad226000000294944415408
|
||||||
|
d7636080820f50b80a0a43d1b0b131c39933d849088348363f1040880f40
|
||||||
|
00212810030009ba422d1cbe5f9a0000000049454e44ae426082
|
||||||
|
|
||||||
4
crates/libremetaverse-imaging-skia/tests/fixtures/lossy-red.webp.hex
vendored
Normal file
4
crates/libremetaverse-imaging-skia/tests/fixtures/lossy-red.webp.hex
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
524946463c000000574542505650382030000000d001009d012a08000800
|
||||||
|
01402625a00274ba01f80003b000fef36997fe6c0ae6b9f7fbffe9707e97
|
||||||
|
07e9707fe9480000
|
||||||
|
|
||||||
8
crates/libremetaverse-imaging-skia/tests/fixtures/multi.ico.hex
vendored
Normal file
8
crates/libremetaverse-imaging-skia/tests/fixtures/multi.ico.hex
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
000001000200
|
||||||
|
01010000010020002c00000026000000
|
||||||
|
02020000010020003800000052000000
|
||||||
|
28000000010000000200000001002000000000000400000000000000000000000000000000000000
|
||||||
|
0000ffff
|
||||||
|
28000000020000000400000001002000000000001000000000000000000000000000000000000000
|
||||||
|
ff0000ffffffffff0000ffff00ff00ff
|
||||||
|
|
||||||
3
crates/libremetaverse-imaging-skia/tests/fixtures/multibyte.wbmp.hex
vendored
Normal file
3
crates/libremetaverse-imaging-skia/tests/fixtures/multibyte.wbmp.hex
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
0000810201
|
||||||
|
ffffffffffffffffffffffffffffffff80
|
||||||
|
|
||||||
7
crates/libremetaverse-imaging-skia/tests/fixtures/palette-offset.gif.hex
vendored
Normal file
7
crates/libremetaverse-imaging-skia/tests/fixtures/palette-offset.gif.hex
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
474946383961040002008400000000001000002000003000004000005000
|
||||||
|
00600000700000800000900000a00000b00000c00000d00000e00000f000
|
||||||
|
000000000000110000220000330000440000550000660000770000880000
|
||||||
|
990000aa0000bb0000cc0000dd0000ee0000ff21f904000a0000002c0000
|
||||||
|
00000400020000070908090a0b0c0d0e0f810021f9040114001a002c0100
|
||||||
|
0100030001000007041f1a1581003b
|
||||||
|
|
||||||
26
crates/libremetaverse-imaging-skia/tests/fixtures/progressive.jpg.hex
vendored
Normal file
26
crates/libremetaverse-imaging-skia/tests/fixtures/progressive.jpg.hex
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
ffd8ffe000104a46494600010101004800480000ffdb0043000806060706
|
||||||
|
05080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20
|
||||||
|
242e2720222c231c1c2837292c30313434341f27393d38323c2e333432ff
|
||||||
|
c2000b080080008001011100ffc400150001010000000000000000000000
|
||||||
|
0000000306ffda0008010100000001824444444444444448744444444444
|
||||||
|
444487444444444444444874444444444444448744444444444444487444
|
||||||
|
444444444444874444444444444448744444444444444487444444444444
|
||||||
|
444874444444444444448744444444444444487444444444444444874444
|
||||||
|
444444444448744444444444444487444444444444444874444444444444
|
||||||
|
44ffc40014100100000000000000000000000000000080ffda0008010100
|
||||||
|
010502007fffc40014100100000000000000000000000000000080ffda00
|
||||||
|
08010100063f02007fffc400151001010000000000000000000000000000
|
||||||
|
0100ffda0008010100013f21082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082082082082082
|
||||||
|
082082082082082082082082082082082082082082082082ffda00080101
|
||||||
|
000000100000000000000000000000000000000000000000000000000000
|
||||||
|
000000000000ffc40014100100000000000000000000000000000080ffda
|
||||||
|
0008010100013f10007fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00
|
||||||
|
ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00
|
||||||
|
ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00
|
||||||
|
ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00
|
||||||
|
ff00ff00ff00ff00ff00ff00ff00ff00ff00ffd9
|
||||||
2
crates/libremetaverse-imaging-skia/tests/fixtures/rgb-lossless.webp.hex
vendored
Normal file
2
crates/libremetaverse-imaging-skia/tests/fixtures/rgb-lossless.webp.hex
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
524946461c000000574542505650384c0f0000002f014000000710f58ffe
|
||||||
|
0722a2ff0100
|
||||||
5
crates/libremetaverse-imaging-skia/tests/fixtures/rgb.png.hex
vendored
Normal file
5
crates/libremetaverse-imaging-skia/tests/fixtures/rgb.png.hex
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
89504e470d0a1a0a0000000d4948445200000020000000200802000000fc
|
||||||
|
18eda30000000467414d41000186a031e8965f00000048494441544889ed
|
||||||
|
d5c10900300c024085ec91fdb772133b442bf4a1f8cee12bb40d043b800a
|
||||||
|
14f81ca0ede47d4c784081020f4a871fc284071428f0a0743823a94081bb
|
||||||
|
7077a3c00182b1f95e3ed793980000000049454e44ae426082
|
||||||
2
crates/libremetaverse-imaging-skia/tests/fixtures/rgb555.bmp.hex
vendored
Normal file
2
crates/libremetaverse-imaging-skia/tests/fixtures/rgb555.bmp.hex
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
424d3a000000000000003600000028000000020000000100000001001000000000000400000000000000000000000000000000000000
|
||||||
|
007ce003
|
||||||
7
crates/libremetaverse-imaging-skia/tests/fixtures/rgba.png.hex
vendored
Normal file
7
crates/libremetaverse-imaging-skia/tests/fixtures/rgba.png.hex
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
89504e470d0a1a0a0000000d494844520000002000000020080600000073
|
||||||
|
7a7af40000000467414d41000186a031e8965f0000006f494441545885ed
|
||||||
|
d6310a80300c46e12764684fa1f73f55048f21c4ddc545781d52e85028fc
|
||||||
|
1f4d28d98a01305e7b7e9cffba33831d75054703ca06a8f90d58a0074e35
|
||||||
|
1e227d805c8254e31bb0420f5cdc2e0079208892ffe2a00136a07b400794
|
||||||
|
3c1004d900195036407f011bf00052201a9cd68fe9670000000049454e44
|
||||||
|
ae426082
|
||||||
1
crates/libremetaverse-imaging-skia/tests/fixtures/small.wbmp.hex
vendored
Normal file
1
crates/libremetaverse-imaging-skia/tests/fixtures/small.wbmp.hex
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
000002028040
|
||||||
6
crates/libremetaverse-imaging-skia/tests/fixtures/straight-alpha.png.hex
vendored
Normal file
6
crates/libremetaverse-imaging-skia/tests/fixtures/straight-alpha.png.hex
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
89504e470d0a1a0a0000000d49484452000000010000000108060000001f
|
||||||
|
15c489000000017352474200aece1ce900000006624b474400ff00ff00ff
|
||||||
|
a0bda793000000097048597300000b1300000b1301009a9c180000000774
|
||||||
|
494d4507de040313163ac721af9d0000001974455874436f6d6d656e7400
|
||||||
|
4372656174656420776974682047494d5057810e170000000d4944415408
|
||||||
|
d763f8ffff7f3d00097b037d178855c50000000049454e44ae426082
|
||||||
3
crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-bottom-up.bmp.hex
vendored
Normal file
3
crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-bottom-up.bmp.hex
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
424d46000000000000003600000028000000020000000200000001001800000000001000000000000000000000000000000000000000
|
||||||
|
ff0000ffffff00000000ff00ff000000
|
||||||
|
|
||||||
3
crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-top-down.bmp.hex
vendored
Normal file
3
crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-top-down.bmp.hex
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
424d4600000000000000360000002800000002000000feffffff01001800000000001000000000000000000000000000000000000000
|
||||||
|
0000ff00ff000000ff0000ffffff0000
|
||||||
|
|
||||||
@@ -18,6 +18,12 @@ sha1 = "0.10"
|
|||||||
sha2 = "0.11"
|
sha2 = "0.11"
|
||||||
uuid = { version = "1.18", features = ["v4"] }
|
uuid = { version = "1.18", features = ["v4"] }
|
||||||
|
|
||||||
|
# Browser and JavaScript WASM targets have no operating-system entropy syscall.
|
||||||
|
# Select getrandom's supported Web Crypto adapter only for that target family.
|
||||||
|
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||||
|
getrandom = { version = "0.4", features = ["wasm_js"] }
|
||||||
|
uuid = { version = "1.18", features = ["v4", "rng-getrandom"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
stats_alloc = "0.1.10"
|
stats_alloc = "0.1.10"
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ they use those APIs directly.
|
|||||||
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
|
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
|
||||||
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
|
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
|
||||||
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
|
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
|
||||||
| `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache |
|
| `libremetaverse-imaging-skia` | Common raster formats through native Skia or pure Rust | Optional `skia` native build/cache; optional `rust-skia` has no native prerequisites |
|
||||||
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
|
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
|
||||||
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
|
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
|
||||||
| `libremetaverse-rendering-mesh-foundry` | Prim, terrain, sculpt, and mesh-asset rendering | Pure Rust |
|
| `libremetaverse-rendering-mesh-foundry` | Prim, terrain, sculpt, and mesh-asset rendering | Pure Rust |
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ allow = []
|
|||||||
allow-workspace = true
|
allow-workspace = true
|
||||||
deny = []
|
deny = []
|
||||||
skip = [
|
skip = [
|
||||||
|
{ crate = "bit-vec@0.8.0", reason = "Approved pinned skia-rs shader parser compatibility line" },
|
||||||
|
{ crate = "bitflags@1.3.2", reason = "Approved pinned pure-Rust PNG compatibility line" },
|
||||||
{ crate = "block-buffer@0.10.4", reason = "Approved RustCrypto digest 0.10 compatibility line" },
|
{ crate = "block-buffer@0.10.4", reason = "Approved RustCrypto digest 0.10 compatibility line" },
|
||||||
{ crate = "cfg_aliases@0.1.1", reason = "Approved older nix build-helper line" },
|
{ crate = "cfg_aliases@0.1.1", reason = "Approved older nix build-helper line" },
|
||||||
{ crate = "const-oid@0.9.6", reason = "Approved DTLS certificate compatibility line" },
|
{ crate = "const-oid@0.9.6", reason = "Approved DTLS certificate compatibility line" },
|
||||||
@@ -47,10 +49,12 @@ skip = [
|
|||||||
{ crate = "digest@0.10.7", reason = "Approved legacy hash and WebRTC compatibility line" },
|
{ crate = "digest@0.10.7", reason = "Approved legacy hash and WebRTC compatibility line" },
|
||||||
{ crate = "getrandom@0.2.17", reason = "Approved elliptic-curve entropy compatibility line" },
|
{ crate = "getrandom@0.2.17", reason = "Approved elliptic-curve entropy compatibility line" },
|
||||||
{ crate = "getrandom@0.3.4", reason = "Approved rand 0.9 entropy compatibility line" },
|
{ crate = "getrandom@0.3.4", reason = "Approved rand 0.9 entropy compatibility line" },
|
||||||
|
{ crate = "hashbrown@0.16.1", reason = "Approved pinned skia-rs geometry compatibility line" },
|
||||||
{ crate = "nix@0.28.0", reason = "Approved machine-address Unix compatibility line" },
|
{ crate = "nix@0.28.0", reason = "Approved machine-address Unix compatibility line" },
|
||||||
{ crate = "nom@7.1.3", reason = "Approved Skia bindgen parser compatibility line" },
|
{ crate = "nom@7.1.3", reason = "Approved Skia bindgen parser compatibility line" },
|
||||||
{ crate = "rand_core@0.6.4", reason = "Approved elliptic-curve random compatibility line" },
|
{ crate = "rand_core@0.6.4", reason = "Approved elliptic-curve random compatibility line" },
|
||||||
{ crate = "rand_core@0.9.5", reason = "Approved rand 0.9 compatibility line" },
|
{ crate = "rand_core@0.9.5", reason = "Approved rand 0.9 compatibility line" },
|
||||||
|
{ crate = "rustc-hash@1.1.0", reason = "Approved pinned skia-rs shader parser compatibility line" },
|
||||||
{ crate = "sha2@0.10.9", reason = "Approved WebRTC RustCrypto compatibility line" },
|
{ crate = "sha2@0.10.9", reason = "Approved WebRTC RustCrypto compatibility line" },
|
||||||
{ crate = "shlex@1.3.0", reason = "Approved Skia bindgen shell parser compatibility line" },
|
{ crate = "shlex@1.3.0", reason = "Approved Skia bindgen shell parser compatibility line" },
|
||||||
{ crate = "syn@2.0.119", reason = "Approved MetaCrate code generator syntax line" },
|
{ crate = "syn@2.0.119", reason = "Approved MetaCrate code generator syntax line" },
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ and [`MeshFoundry` guide](../crates/libremetaverse-rendering-mesh-foundry/README
|
|||||||
| Managed images and TGA | enabled | n/a | none |
|
| Managed images and TGA | enabled | n/a | none |
|
||||||
| JPEG 2000 | disabled | `libremetaverse-imaging/jpeg2000` | OpenJPEG 2.5.x |
|
| JPEG 2000 | disabled | `libremetaverse-imaging/jpeg2000` | OpenJPEG 2.5.x |
|
||||||
| JPEG 2000 (pure Rust) | disabled | `libremetaverse-imaging/rust-j2k` | none (`j2k` 0.8.1) |
|
| JPEG 2000 (pure Rust) | disabled | `libremetaverse-imaging/rust-j2k` | none (`j2k` 0.8.1) |
|
||||||
| BMP/GIF/ICO/JPEG/PNG/WBMP/WebP | disabled | `libremetaverse-imaging-skia/skia` | Skia |
|
| BMP/GIF/ICO/JPEG/PNG/WBMP/WebP (pure Rust) | disabled | `libremetaverse-imaging-skia/rust-skia` | none (`skia-rs-codec` 0.3.0 plus `image-webp` 0.2.4) |
|
||||||
|
| BMP/GIF/ICO/JPEG/PNG/WBMP/WebP (native) | disabled | `libremetaverse-imaging-skia/skia` | Skia |
|
||||||
| Prim and sculpt meshing, OBJ ingestion | enabled | n/a | none |
|
| Prim and sculpt meshing, OBJ ingestion | enabled | n/a | none |
|
||||||
|
|
||||||
OpenJPEG is a non-default workspace member so release tooling can package the
|
OpenJPEG is a non-default workspace member so release tooling can package the
|
||||||
@@ -26,10 +27,11 @@ adapter explicitly, and imaging reaches it only through the optional
|
|||||||
dependency. The independent `rust-j2k` feature reaches only the audited
|
dependency. The independent `rust-j2k` feature reaches only the audited
|
||||||
pure-Rust `j2k` graph; enabling both features keeps both explicit codec types
|
pure-Rust `j2k` graph; enabling both features keeps both explicit codec types
|
||||||
available for interoperability testing. Skia is likewise an optional,
|
available for interoperability testing. Skia is likewise an optional,
|
||||||
target-specific dependency. The
|
target-specific dependency. The consolidated required Gitea gate exercises the
|
||||||
consolidated required Gitea gate exercises both optional features on
|
native feature, while a dedicated `ubuntu-latest` job tests `rust-skia`, audits
|
||||||
`ubuntu-latest` while its minimal-feature check proves that no native codec is
|
its normal/build graph without installing native codec tools, and compiles the
|
||||||
needed for the owned Rust and translated compatibility tests.
|
same code for WASM. Minimal-feature checks still prove no codec is needed for
|
||||||
|
the owned Rust and translated compatibility tests.
|
||||||
|
|
||||||
## Bounds and rendering contract
|
## Bounds and rendering contract
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ Optional boundaries are explicit:
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `jpeg2000` | J2K/JP2 through the safe OpenJPEG adapter | OpenJPEG 2.5.4 or newer |
|
| `jpeg2000` | J2K/JP2 through the safe OpenJPEG adapter | OpenJPEG 2.5.4 or newer |
|
||||||
| `rust-j2k` | J2K/JP2 through `RustJ2kCodec` | none; exact pure-Rust `j2k` 0.8.1 |
|
| `rust-j2k` | J2K/JP2 through `RustJ2kCodec` | none; exact pure-Rust `j2k` 0.8.1 |
|
||||||
|
| `rust-skia` | BMP/GIF/ICO/JPEG/PNG/WBMP/WebP through `RustSkiaTextureCodec` | none; exact pure-Rust `skia-rs-codec` 0.3.0 and `image-webp` 0.2.4 |
|
||||||
| `skia` | PNG/JPEG/WebP and other Skia formats | Skia 0.99 target cache or documented source tools |
|
| `skia` | PNG/JPEG/WebP and other Skia formats | Skia 0.99 target cache or documented source tools |
|
||||||
| `vorbis` | PCM to Ogg Vorbis | the locked `vorbis_rs` native build stack |
|
| `vorbis` | PCM to Ogg Vorbis | the locked `vorbis_rs` native build stack |
|
||||||
| default WebRTC | native ICE/DTLS/SRTP/RTP/SCTP and Opus | system libopus 1.3 or newer |
|
| default WebRTC | native ICE/DTLS/SRTP/RTP/SCTP and Opus | system libopus 1.3 or newer |
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ they use those APIs directly.
|
|||||||
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
|
| `libremetaverse-types` | UUIDs, vectors, matrices, colors, cancellation, compatibility collections, and boundary types | Pure Rust |
|
||||||
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
|
| `libremetaverse-structured-data` | LLSD/OSD XML, JSON, binary, and notation | Pure Rust |
|
||||||
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
|
| `libremetaverse-imaging` | Managed images, TGA/DDS, codec traits | Optional `jpeg2000` or pure-Rust `rust-j2k` |
|
||||||
| `libremetaverse-imaging-skia` | Common raster formats through Skia | Optional `skia`; native Skia build/cache |
|
| `libremetaverse-imaging-skia` | Common raster formats through native Skia or pure Rust | Optional `skia` native build/cache; optional `rust-skia` has no native prerequisites |
|
||||||
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
|
| `libremetaverse-prim-mesher` | Legacy prim and sculpt geometry | Pure Rust |
|
||||||
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
|
| `libremetaverse-rendering-simple` | Deterministic reference geometry | Pure Rust |
|
||||||
| `libremetaverse-rendering-mesh-foundry` | Prim, terrain, sculpt, and mesh-asset rendering | Pure Rust |
|
| `libremetaverse-rendering-mesh-foundry` | Prim, terrain, sculpt, and mesh-asset rendering | Pure Rust |
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schema": 1,
|
"schema": 1,
|
||||||
"cargo_lock_sha256": "68988caa2c014bf2c67563df3dd0a8348d67eeb06559649798463fd8211fc0cb",
|
"cargo_lock_sha256": "a547e07459a810d61571eca6775cebea871fd2874508a494350918fddccf8d6d",
|
||||||
"provenance_policy_sha256": "f95475a2284ab282e9432865d4a7ed103498a56ed5ec2393017bc312c77da890",
|
"provenance_policy_sha256": "f95475a2284ab282e9432865d4a7ed103498a56ed5ec2393017bc312c77da890",
|
||||||
"upstream_repository": "https://github.com/cinderblocks/libremetaverse",
|
"upstream_repository": "https://github.com/cinderblocks/libremetaverse",
|
||||||
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
|
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": ".gitea/workflows/ci.yml",
|
"path": ".gitea/workflows/ci.yml",
|
||||||
"bytes": 6440,
|
"bytes": 7567,
|
||||||
"sha256": "6241a445155b0691896af98310b18858e0c38537dca70c80c5c0bd9cf8f1c0ca"
|
"sha256": "ae8f50aaf0ab6bd07cfff49d75ba7cd1f051bbd6c7599dc8f1d5f239db5b8561"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": ".gitea/workflows/release.yml",
|
"path": ".gitea/workflows/release.yml",
|
||||||
@@ -42,8 +42,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Cargo.lock",
|
"path": "Cargo.lock",
|
||||||
"bytes": 103842,
|
"bytes": 117042,
|
||||||
"sha256": "68988caa2c014bf2c67563df3dd0a8348d67eeb06559649798463fd8211fc0cb"
|
"sha256": "a547e07459a810d61571eca6775cebea871fd2874508a494350918fddccf8d6d"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "Cargo.toml",
|
"path": "Cargo.toml",
|
||||||
@@ -62,13 +62,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "README.md",
|
"path": "README.md",
|
||||||
"bytes": 35953,
|
"bytes": 36207,
|
||||||
"sha256": "dea4a52f12e5885e2c53356c56b122c9bbf00382cbff21ff179e05b1d8714f05"
|
"sha256": "c3f0ff673ad886783314122cf49162e59ccfa4d82a928023d930d60bf521c6b3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "RUSTREWRITE.md",
|
"path": "RUSTREWRITE.md",
|
||||||
"bytes": 54472,
|
"bytes": 55217,
|
||||||
"sha256": "b3bc471cb82e76cca0c3d251090634de3ed29e24ef91b01d3cc89723e31854be"
|
"sha256": "487dce943fbe823ab5967bbedff506e1229b70508cb73d33fe6726ee11a2fc68"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "api/API-COVERAGE.md",
|
"path": "api/API-COVERAGE.md",
|
||||||
@@ -102,13 +102,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "api/SEMVER-AUDIT.md",
|
"path": "api/SEMVER-AUDIT.md",
|
||||||
"bytes": 5558,
|
"bytes": 5608,
|
||||||
"sha256": "3c44b4b0ea579d975492fd5f9395a29fc597e43b126f8cbae4a0c14792232dd0"
|
"sha256": "91c8dfc22d6f6d411fddc0c52ea02f43245c303eb0fe6d8bac2d46046d7a4ddd"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "api/SEMVER-BASELINE.json",
|
"path": "api/SEMVER-BASELINE.json",
|
||||||
"bytes": 5901,
|
"bytes": 6087,
|
||||||
"sha256": "cd422369af58c6f60dbdda202ae4bb331f68ca3aacb5171839512100c027432e"
|
"sha256": "41d77e564f53f7757c8ce7be56abc310d92edf094a0b9ee516944ad2389c0025"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "api/SHIM-COVERAGE.md",
|
"path": "api/SHIM-COVERAGE.md",
|
||||||
@@ -212,8 +212,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ci/ci-coverage.json",
|
"path": "ci/ci-coverage.json",
|
||||||
"bytes": 5593,
|
"bytes": 5694,
|
||||||
"sha256": "241e7bc687b1c2395885e4cd2a95c446e5d4847e3bf9a34d8cee3d76bcbc2903"
|
"sha256": "40eed10def683f978c65deba5d2c09f463330fe1cd6357efafc875d86ed1afa3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ci/concurrency-thresholds.json",
|
"path": "ci/concurrency-thresholds.json",
|
||||||
@@ -222,8 +222,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ci/dependency-policy.json",
|
"path": "ci/dependency-policy.json",
|
||||||
"bytes": 10851,
|
"bytes": 12019,
|
||||||
"sha256": "781d497a7a0ddd53fb9158e74e1c5f967eaf3b97535596b42bf34fa38e59b482"
|
"sha256": "5d35e2940c22da4c7a488a4ace7dc55ab7293a8ea713b6d71a62d1d0af2ac9cb"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ci/evidence/api-audit.json",
|
"path": "ci/evidence/api-audit.json",
|
||||||
@@ -267,8 +267,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ci/release-matrix.json",
|
"path": "ci/release-matrix.json",
|
||||||
"bytes": 8560,
|
"bytes": 9206,
|
||||||
"sha256": "f6a641f66c023cd00d5d8b8692b5d6f4a8273fee8e8b5411cab4481de1b0f602"
|
"sha256": "c87d86bd754b0c6d98971e0bae83b89bee33be1068f080b02ce897adbd22414e"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "codegen/README.md",
|
"path": "codegen/README.md",
|
||||||
@@ -332,13 +332,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging-skia/Cargo.toml",
|
"path": "crates/libremetaverse-imaging-skia/Cargo.toml",
|
||||||
"bytes": 1440,
|
"bytes": 1691,
|
||||||
"sha256": "0fb038f36280490487eb3f9e24176abd0f002504918b7bdac83ca319d92298e2"
|
"sha256": "013ba0f82c12f654d3b7d90aea4088eb5af0f888fc810736821b9dc9eef20d44"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging-skia/README.md",
|
"path": "crates/libremetaverse-imaging-skia/README.md",
|
||||||
"bytes": 3196,
|
"bytes": 6542,
|
||||||
"sha256": "8e1475598b33502d8b7de9528cf925919232dd57ad5c84cce9a382a9b5a22dc2"
|
"sha256": "9812fa5c5221497a9a3200564aa9d29425ec7f79ff0d2e3e86455c04cb1ff460"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging-skia/src/backend.rs",
|
"path": "crates/libremetaverse-imaging-skia/src/backend.rs",
|
||||||
@@ -352,13 +352,123 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging-skia/src/lib.rs",
|
"path": "crates/libremetaverse-imaging-skia/src/lib.rs",
|
||||||
"bytes": 811,
|
"bytes": 1182,
|
||||||
"sha256": "a180686de4aa47d167e61d1198676dd0fa817490669090b177fc9f662069803d"
|
"sha256": "8a8a49b2802b0012e0f4731c9a40bfa3c12784716ed2ddb17dad07ef8cd7a4f3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging-skia/src/skia_codec.rs",
|
"path": "crates/libremetaverse-imaging-skia/src/skia_codec.rs",
|
||||||
"bytes": 21674,
|
"bytes": 52736,
|
||||||
"sha256": "59215a746a0842609ba8a4c86dca0c09c38043a0ea832416159a2d555c612827"
|
"sha256": "373cb9c033dc1d2ea40cee19fc1212860882ac5f679b1952fd5b2ffd72b46809"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/README.md",
|
||||||
|
"bytes": 1852,
|
||||||
|
"sha256": "d84610151dceba3012549a2b001d49cc4679e0160713dbcafc11f748f7b19edb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/alpha.webp.hex",
|
||||||
|
"bytes": 79,
|
||||||
|
"sha256": "f7e268437d69a569a27ee15fb3c1c21785afe27c4ad1f99fe63e362cf85af718"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/animated.webp.hex",
|
||||||
|
"bytes": 692,
|
||||||
|
"sha256": "90accfdcb7c2548162d641990f9c7dc5276b81164137467b274b9ab65e12ec5c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/baseline.jpg.hex",
|
||||||
|
"bytes": 669,
|
||||||
|
"sha256": "c614e00c9ab1247ac4957dde699e62a82f61f1ea25bbd02a8f86dac27fc0f2c8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/bgrx32.bmp.hex",
|
||||||
|
"bytes": 126,
|
||||||
|
"sha256": "9cdb2db245a0d4ea5289c36e8ef3c55e8a1d9933b2854760dfc2b3474fbcd299"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/bottom-up.bmp.hex",
|
||||||
|
"bytes": 502,
|
||||||
|
"sha256": "dc73f5816020b36c312b48d86afe4fac7bbe250ca4255f7a84b654cb610d7bf6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/gray-alpha.png.hex",
|
||||||
|
"bytes": 257,
|
||||||
|
"sha256": "ba2bd4b3ec1286aecfd33141474a2855d697ee88888881396e517a9fbfc1781e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/gray.png.hex",
|
||||||
|
"bytes": 281,
|
||||||
|
"sha256": "0122a5fb4c9ec3398056b74cf503492df06dea9b174abde61b05853eaf5d781f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/interlaced-palette.png.hex",
|
||||||
|
"bytes": 237,
|
||||||
|
"sha256": "d3e76f043e8da40cce95cfb75ac1d9a34a5dc6633b87258f62c77830c9c3d311"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/lossy-red.webp.hex",
|
||||||
|
"bytes": 140,
|
||||||
|
"sha256": "5a31db73c00a7543b1831a8488c8c393c91042c35d10ee874ab2b91060524491"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/multi.ico.hex",
|
||||||
|
"bytes": 284,
|
||||||
|
"sha256": "75f085b4a18c72fbf2404bd16c5d3c6ffce16e6e8823c7d5dd12f4aa54e4f179"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/multibyte.wbmp.hex",
|
||||||
|
"bytes": 47,
|
||||||
|
"sha256": "fd1e97b193d36d1c4d5650b41081487d4ecacbfe0277d29e61a3c6dc9d9ce5e6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/palette-offset.gif.hex",
|
||||||
|
"bytes": 337,
|
||||||
|
"sha256": "b53f9756afa1a8409ba800fadc51113664210eda9d16afbbf4465a509c230cbd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/progressive.jpg.hex",
|
||||||
|
"bytes": 1566,
|
||||||
|
"sha256": "61244f0a07cdb9bf6908c8ec8f896e0a9a6385f65cffc5fb99407c772e3a4a5a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/rgb-lossless.webp.hex",
|
||||||
|
"bytes": 74,
|
||||||
|
"sha256": "e8ab53c5c310c356bccaf7f2baa40190ff39add1c68307fa816e769cfb044f61"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/rgb.png.hex",
|
||||||
|
"bytes": 295,
|
||||||
|
"sha256": "1e5ec2ef16d17aa895651ae49a05e173fb631a8addf2400fa0376788f23e8656"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/rgb555.bmp.hex",
|
||||||
|
"bytes": 118,
|
||||||
|
"sha256": "3e3fd2851ae755c990d9a3d0b2b48d47e67e76a812782cc1107feebb9a2bfca5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/rgba.png.hex",
|
||||||
|
"bytes": 375,
|
||||||
|
"sha256": "2f6af08ab8092a3705a7776727b2791be4a041ceacde64651993f4bb7e96eb04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/small.wbmp.hex",
|
||||||
|
"bytes": 13,
|
||||||
|
"sha256": "00625cd5781673ec81928d2c08a73516ba820fb46cfe155779c321335068ecab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/straight-alpha.png.hex",
|
||||||
|
"bytes": 362,
|
||||||
|
"sha256": "123f0a325427e2810c0544d3dc24e5943757a4f86f0e2892f10e7a974cc01156"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-bottom-up.bmp.hex",
|
||||||
|
"bytes": 143,
|
||||||
|
"sha256": "be53e0cd06441f5795b11d1b517d1542459952d0aa464ec5c7f9d443a42111df"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "crates/libremetaverse-imaging-skia/tests/fixtures/two-by-two-top-down.bmp.hex",
|
||||||
|
"bytes": 143,
|
||||||
|
"sha256": "83bbf5c1c66e93c7aa413428d760230bca205eb4a1c4f3fc60f9fc63560c285f"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-imaging/Cargo.toml",
|
"path": "crates/libremetaverse-imaging/Cargo.toml",
|
||||||
@@ -702,8 +812,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-types/Cargo.toml",
|
"path": "crates/libremetaverse-types/Cargo.toml",
|
||||||
"bytes": 505,
|
"bytes": 837,
|
||||||
"sha256": "674f227613ac9776f7ea09fb59a6504850830bd8bfc6e62e96ee691226635ae4"
|
"sha256": "5751090243c10be962db766afa5bcede1074d6d63d3c715528f922bdc440e3e4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse-types/benches/geometry.rs",
|
"path": "crates/libremetaverse-types/benches/geometry.rs",
|
||||||
@@ -892,8 +1002,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse/README.md",
|
"path": "crates/libremetaverse/README.md",
|
||||||
"bytes": 13059,
|
"bytes": 13123,
|
||||||
"sha256": "871b0b94073aafa46235bba7d150c13d4c4900da5e4e2d82201604365d2c5c40"
|
"sha256": "d0fa677f09dcc7e85f1b63e92cce6316e57103583916e166727d1e999173105a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "crates/libremetaverse/assets/avatar_lad.xml",
|
"path": "crates/libremetaverse/assets/avatar_lad.xml",
|
||||||
@@ -1522,8 +1632,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "deny.toml",
|
"path": "deny.toml",
|
||||||
"bytes": 2738,
|
"bytes": 3140,
|
||||||
"sha256": "2186fbadd60f11b672c47a916b89dcfc350c3ed922595d9ecf48346a0767f364"
|
"sha256": "aa3d63fd17c6647be6c4b2d6467ca6282de588a8253a9d6a938a432287a8f2eb"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/agent-manager.md",
|
"path": "docs/agent-manager.md",
|
||||||
@@ -1582,8 +1692,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/imaging-meshing.md",
|
"path": "docs/imaging-meshing.md",
|
||||||
"bytes": 3678,
|
"bytes": 3967,
|
||||||
"sha256": "c63e434d5181dc903c83f00c7649ee2040028c6d4bda698f57da8c1c3b1416c6"
|
"sha256": "a220d1d907a0359d6a82168dee121721895950bd86d2b0ea25f6e998bf5744f3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/inventory.md",
|
"path": "docs/inventory.md",
|
||||||
@@ -1612,8 +1722,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/release-candidate.md",
|
"path": "docs/release-candidate.md",
|
||||||
"bytes": 4327,
|
"bytes": 4476,
|
||||||
"sha256": "20aa8c39de842ca1dee15808c44f1e71ee33441796b17d03feea8e14ef99165f"
|
"sha256": "25e5a581235539b9145a9030b9f3af9d78f6a22cfc7587b1090f8c19b8653e26"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/release-ci-matrix.md",
|
"path": "docs/release-ci-matrix.md",
|
||||||
@@ -1627,8 +1737,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/rust-api-guide.md",
|
"path": "docs/rust-api-guide.md",
|
||||||
"bytes": 12058,
|
"bytes": 12122,
|
||||||
"sha256": "db4d0ee7986eebe9434e5c51ca65a31ffc3b32323240d9dc62cbd931b21b21b1"
|
"sha256": "25d2b333be7106c68bb9d6e1a8149d8abd333566c6705af7a9fb7e97ac7163e4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "docs/social.md",
|
"path": "docs/social.md",
|
||||||
@@ -2517,8 +2627,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "tools/ci-matrix/src/api_surface.rs",
|
"path": "tools/ci-matrix/src/api_surface.rs",
|
||||||
"bytes": 48586,
|
"bytes": 48993,
|
||||||
"sha256": "a82ac15da446f2f393ba267f8c7537d43cb4595a6be3e08f27d2f718e2aad4e8"
|
"sha256": "2c4248ca2cb16c9ae84e25af823f5a45a3f7840519baa8f08d85c67212df8b4e"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "tools/ci-matrix/src/artifact.rs",
|
"path": "tools/ci-matrix/src/artifact.rs",
|
||||||
@@ -2542,8 +2652,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "tools/ci-matrix/src/lib.rs",
|
"path": "tools/ci-matrix/src/lib.rs",
|
||||||
"bytes": 21271,
|
"bytes": 21338,
|
||||||
"sha256": "53f4286d600c78d7a3ea593e7d663854e722787573dc5bbf3e48d41e28ac8267"
|
"sha256": "cd2d54c1ee8182843af43c271ff1592040c32de254d91bd146aeb822ae3a9a4e"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "tools/ci-matrix/src/main.rs",
|
"path": "tools/ci-matrix/src/main.rs",
|
||||||
@@ -2664,13 +2774,13 @@
|
|||||||
"generated_release_files": [
|
"generated_release_files": [
|
||||||
{
|
{
|
||||||
"path": "release/DEPENDENCY-LICENSES.json",
|
"path": "release/DEPENDENCY-LICENSES.json",
|
||||||
"bytes": 230084,
|
"bytes": 259721,
|
||||||
"sha256": "64ee30790d4b3b643514098184bf15b2e9901fe177333dbd7950b4311a47292e"
|
"sha256": "5f80b45ab18a45365673b55b52d68318bc31f602ce2f6559f573027cc446c58e"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "release/THIRD-PARTY-NOTICES.md",
|
"path": "release/THIRD-PARTY-NOTICES.md",
|
||||||
"bytes": 897381,
|
"bytes": 980767,
|
||||||
"sha256": "47d10a98d94bfe09124cbbfcf57f91a34231286aaec71a3265372ee9006d3eab"
|
"sha256": "c4d381944a9b57277963d2a5ee4e23a9a064c2ba93a676a49e023931b53a71d6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "release/NATIVE-LICENSES.md",
|
"path": "release/NATIVE-LICENSES.md",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -932,6 +932,16 @@ fn validate_features(name: &str, actual: &BTreeMap<String, Vec<String>>) -> Resu
|
|||||||
]),
|
]),
|
||||||
"libremetaverse-imaging-skia" => BTreeMap::from([
|
"libremetaverse-imaging-skia" => BTreeMap::from([
|
||||||
("default".to_owned(), Vec::new()),
|
("default".to_owned(), Vec::new()),
|
||||||
|
(
|
||||||
|
"rust-skia".to_owned(),
|
||||||
|
vec![
|
||||||
|
"dep:image-webp".to_owned(),
|
||||||
|
"dep:skia-rs-codec".to_owned(),
|
||||||
|
"skia-rs-codec/gif".to_owned(),
|
||||||
|
"skia-rs-codec/jpeg".to_owned(),
|
||||||
|
"skia-rs-codec/png".to_owned(),
|
||||||
|
],
|
||||||
|
),
|
||||||
("skia".to_owned(), vec!["dep:skia-safe".to_owned()]),
|
("skia".to_owned(), vec!["dep:skia-safe".to_owned()]),
|
||||||
]),
|
]),
|
||||||
"libremetaverse-voice-webrtc" => BTreeMap::from([
|
"libremetaverse-voice-webrtc" => BTreeMap::from([
|
||||||
@@ -1232,7 +1242,7 @@ The exact mapping, exported-marker, feature, and normalized Rust declaration has
|
|||||||
- .NET events become `subscribe_*` calls returning an owned `Subscription`; callbacks are `Send + Sync` and dispatch outside internal locks.\n\
|
- .NET events become `subscribe_*` calls returning an owned `Subscription`; callbacks are `Send + Sync` and dispatch outside internal locks.\n\
|
||||||
- `IDisposable` becomes explicit idempotent shutdown plus `Drop`; cancellation remains a typed `Error::Cancelled`.\n\
|
- `IDisposable` becomes explicit idempotent shutdown plus `Drop`; cancellation remains a typed `Error::Cancelled`.\n\
|
||||||
- Closed C# enums retain fixed discriminants and are SemVer-breaking to extend; flags retain unknown bits, while public Rust error enums are `non_exhaustive`.\n\
|
- Closed C# enums retain fixed discriminants and are SemVer-breaking to extend; flags retain unknown bits, while public Rust error enums are `non_exhaustive`.\n\
|
||||||
- Optional native backends remain feature-gated (`jpeg2000`, `skia`, `vorbis`, `real-audio`); default and empty-default sets are part of the baseline.\n\
|
- Optional native and pure-Rust backends remain feature-gated (`jpeg2000`, `rust-j2k`, `skia`, `rust-skia`, `vorbis`, `real-audio`); default and empty-default sets are part of the baseline.\n\
|
||||||
- Capability HTTP injection uses project-owned `HttpMessageHandler`, `CapsHttpLimits`, and `with_native_transport`; the internal `reqwest` client is not part of the public surface.\n\
|
- Capability HTTP injection uses project-owned `HttpMessageHandler`, `CapsHttpLimits`, and `with_native_transport`; the internal `reqwest` client is not part of the public surface.\n\
|
||||||
- External C# signature types map to core/std, adopted cross-platform crates, or project-owned boundary types; no third-party crate path leaks through mapped signatures or public Rust declarations.\n\n\
|
- External C# signature types map to core/std, adopted cross-platform crates, or project-owned boundary types; no third-party crate path leaks through mapped signatures or public Rust declarations.\n\n\
|
||||||
## Compile consumers\n\n\
|
## Compile consumers\n\n\
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const REQUIRED_PROFILES: [&str; 7] = [
|
|||||||
"windows-stable-portable",
|
"windows-stable-portable",
|
||||||
"macos-stable-portable",
|
"macos-stable-portable",
|
||||||
];
|
];
|
||||||
const REQUIRED_FEATURE_SETS: [&str; 12] = [
|
const REQUIRED_FEATURE_SETS: [&str; 13] = [
|
||||||
"all-features",
|
"all-features",
|
||||||
"dds-bc67",
|
"dds-bc67",
|
||||||
"default",
|
"default",
|
||||||
@@ -48,11 +48,12 @@ const REQUIRED_FEATURE_SETS: [&str; 12] = [
|
|||||||
"no-default-features",
|
"no-default-features",
|
||||||
"real-audio",
|
"real-audio",
|
||||||
"rust-j2k",
|
"rust-j2k",
|
||||||
|
"rust-skia",
|
||||||
"skia",
|
"skia",
|
||||||
"tests",
|
"tests",
|
||||||
"vorbis",
|
"vorbis",
|
||||||
];
|
];
|
||||||
const REQUIRED_FEATURES: [(&str, &str); 8] = [
|
const REQUIRED_FEATURES: [(&str, &str); 9] = [
|
||||||
("libremetaverse", "dds-bc67"),
|
("libremetaverse", "dds-bc67"),
|
||||||
("libremetaverse", "jpeg2000"),
|
("libremetaverse", "jpeg2000"),
|
||||||
("libremetaverse", "rust-j2k"),
|
("libremetaverse", "rust-j2k"),
|
||||||
@@ -60,6 +61,7 @@ const REQUIRED_FEATURES: [(&str, &str); 8] = [
|
|||||||
("libremetaverse-imaging", "jpeg2000"),
|
("libremetaverse-imaging", "jpeg2000"),
|
||||||
("libremetaverse-imaging", "rust-j2k"),
|
("libremetaverse-imaging", "rust-j2k"),
|
||||||
("libremetaverse-imaging-skia", "skia"),
|
("libremetaverse-imaging-skia", "skia"),
|
||||||
|
("libremetaverse-imaging-skia", "rust-skia"),
|
||||||
("libremetaverse-voice-webrtc", "real-audio"),
|
("libremetaverse-voice-webrtc", "real-audio"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user