feat(imaging): add pure-Rust Skia backend (#112)
This commit is contained in:
@@ -6,10 +6,43 @@ exposes a `skia-safe` type and never discovers or links Skia.
|
||||
|
||||
## Features and formats
|
||||
|
||||
The default feature set has no Skia dependency. `SkiaTextureCodec::decode`
|
||||
returns a typed `InvalidOperation` error in that configuration, while conversion
|
||||
from the checked project-owned `backend::SKBitmap` remains available for tests
|
||||
and callers that already own decoded pixels.
|
||||
The default feature set has no Skia dependency. `SkiaTextureCodec::decode` and
|
||||
`RustSkiaTextureCodec::decode` return a typed `InvalidOperation` error when
|
||||
their respective feature is disabled, while conversion from the checked
|
||||
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:
|
||||
|
||||
@@ -17,7 +50,7 @@ Enable native decoding with:
|
||||
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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
|
||||
`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.
|
||||
Products that redistribute the resulting native artifacts must preserve the
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user