rosace_render/image.rs
1/// Image cache policy controlling when the local cache is consulted.
2#[derive(Debug, Clone, Copy)]
3pub enum CachePolicy {
4 /// Fetch from the network; fall back to cache on failure.
5 NetworkFirst,
6 /// Use the cache if available; fetch from network otherwise.
7 CacheFirst,
8 /// Never use the cache; always fetch from the network.
9 NoCache,
10}
11
12/// Controls how an image fills its layout bounds.
13#[derive(Debug, Clone, Copy)]
14pub enum ImageFit {
15 /// Stretch to fill the bounds, ignoring aspect ratio.
16 Fill,
17 /// Scale uniformly to fit within the bounds, preserving aspect ratio.
18 Contain,
19 /// Scale uniformly to cover the bounds, clipping if necessary.
20 Cover,
21 /// Like [`Contain`], but never upscales below natural size.
22 ///
23 /// [`Contain`]: ImageFit::Contain
24 ScaleDown,
25 /// Render at the image's natural pixel size; no scaling.
26 None,
27}
28
29/// A decoded image ready for rendering.
30///
31/// Full decode and cache support will be implemented in Phase 2. Phase 1
32/// supports PNG decoding via `tiny-skia`.
33#[derive(Debug, Clone)]
34pub struct ImageHandle {
35 /// Image width in pixels.
36 pub width: u32,
37 /// Image height in pixels.
38 pub height: u32,
39 /// Raw RGBA pixel data, row-major, 4 bytes per pixel.
40 pub pixels: Vec<u8>,
41}
42
43impl ImageHandle {
44 /// Decode a PNG image from raw bytes.
45 ///
46 /// Returns `None` if the bytes are not valid PNG data.
47 pub fn from_png_bytes(bytes: &[u8]) -> Option<Self> {
48 let pixmap = tiny_skia::Pixmap::decode_png(bytes).ok()?;
49 Some(Self {
50 width: pixmap.width(),
51 height: pixmap.height(),
52 pixels: pixmap.data().to_vec(),
53 })
54 }
55}