127 lines
6.4 KiB
Markdown
127 lines
6.4 KiB
Markdown
# MetaCrate Skia adapter
|
|
|
|
This crate implements the pinned `SkiaTextureCodec` behavior at a bounded,
|
|
project-owned image boundary. The core `libremetaverse-imaging` crate never
|
|
exposes a `skia-safe` type and never discovers or links Skia.
|
|
|
|
## Features and formats
|
|
|
|
The default feature set enables the pure-Rust `rust-skia` backend and has no
|
|
native Google 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
|
|
```
|
|
|
|
`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 with the workspace Rust 1.97.1 toolchain; both selected direct
|
|
codecs declare older compatible Rust floors.
|
|
|
|
Enable native decoding with:
|
|
|
|
```sh
|
|
cargo test -p libremetaverse-imaging-skia --features skia
|
|
```
|
|
|
|
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
|
|
strides and owned Rust buffers.
|
|
|
|
The mapped C# adapter exposes decoding and `SKBitmap`-to-`ManagedImage`
|
|
conversion only; it has no encoding or resize method. Encoding selection stays
|
|
with the format-specific imaging APIs, and callers use `ManagedImage`'s checked
|
|
resize methods after decoding. Premultiplied pixels are converted to straight
|
|
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
|
|
and Cargo feature set match a published archive. MetaCrate deliberately selects
|
|
the published WebP-capable feature sets:
|
|
|
|
- Linux and Windows: JPEG, PDF, SVG, text layout, Vulkan, and WebP;
|
|
- macOS: JPEG, PDF, SVG, text layout, and WebP.
|
|
|
|
Vulkan is selected on Linux and Windows only to match the published CPU/WebP
|
|
archive; this adapter does not create a GPU context or call a platform graphics
|
|
API. The same feature is therefore usable on macOS, Linux, and Windows without
|
|
leaking platform-specific behavior.
|
|
|
|
Build prerequisites for the supported desktop targets are:
|
|
|
|
- Linux: a C++ linker/runtime, `curl`, `pkg-config`, FreeType, and Fontconfig;
|
|
- macOS: Xcode command-line tools and `curl`;
|
|
- Windows MSVC: the Rust MSVC toolchain, Visual Studio C++ build tools, and
|
|
`curl`.
|
|
|
|
The build script downloads cache archives from the `rust-skia/skia-binaries`
|
|
GitHub releases. Pin or mirror `SKIA_BINARIES_URL` in offline/reproducible build
|
|
environments. `FORCE_SKIA_BINARIES_DOWNLOAD=1` makes a missing archive fail
|
|
instead of compiling Skia. If no archive matches and that variable is absent,
|
|
rust-skia falls back to a source build, which additionally requires Python 3,
|
|
Ninja, and an LLVM/Clang toolchain. `FORCE_SKIA_BUILD=1` selects that path
|
|
explicitly.
|
|
|
|
## Licensing and redistribution
|
|
|
|
`skia-safe` and rust-skia's bindings are MIT licensed; the linked Skia library
|
|
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.
|