shuyi_ui/frame/
portrait.rs1#[cfg(not(feature = "std"))]
6use crate::float::Float;
7use shuyi_assets::image::{ImageId, ImageInfo};
8
9use crate::frame::glyph_buffer::{GlyphBuffer, Layer, PxRect, Rect, Sprite};
10
11pub fn fit_whole_scale(size: ImageInfo, frame: PxRect) -> Option<PxRect> {
16 let (w, h) = (i64::from(size.width), i64::from(size.height));
17 if w == 0 || h == 0 {
18 return None;
19 }
20 let scale = (i64::from(frame.w) / w).min(i64::from(frame.h) / h);
21 if scale < 1 {
22 return None;
23 }
24 let (w, h) = (
26 i32::try_from(w * scale).ok()?,
27 i32::try_from(h * scale).ok()?,
28 );
29 Some(Rect::new(
30 frame.x + (frame.w - w) / 2,
31 frame.y + (frame.h - h) / 2,
32 w,
33 h,
34 ))
35}
36
37#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] pub fn dim_opacity(dim: f32) -> u8 {
41 (255.0 * (1.0 - dim)).round().clamp(0.0, 255.0) as u8
42}
43
44pub fn draw_fitted(
52 buf: &mut GlyphBuffer,
53 (x, y): (i32, i32),
54 (w, h): (i32, i32),
55 (image, size): (ImageId, ImageInfo),
56 dim: f32,
57 mirror: bool,
58) {
59 let (cw, ch) = buf.spec().cell_px();
60 let frame = Rect::new(
61 x.saturating_mul(cw),
62 y.saturating_mul(ch),
63 w.saturating_mul(cw),
64 h.saturating_mul(ch),
65 );
66 let src = (i32::try_from(size.width), i32::try_from(size.height));
67 if let (Some(dest), (Ok(w), Ok(h))) = (fit_whole_scale(size, frame), src) {
68 buf.add_sprite(Sprite {
69 flip_x: mirror,
70 opacity: dim_opacity(dim),
71 ..Sprite::new(image, Rect::new(0, 0, w, h), dest, Layer::Under)
72 });
73 }
74}
75
76#[cfg(test)]
77mod tests;