background/
background.rs

1#![deny(warnings)]
2
3extern crate orbclient;
4extern crate orbimage;
5
6use std::env;
7
8use orbclient::{Color, EventOption, Renderer, Window, WindowFlag};
9use orbimage::Image;
10
11#[derive(Clone, Copy, Debug)]
12enum BackgroundMode {
13    /// Do not resize the image, just center it
14    Center,
15    /// Resize the image to the display size
16    Fill,
17    /// Resize the image - keeping its aspect ratio, and fit it to the display with blank space
18    Scale,
19    /// Resize the image - keeping its aspect ratio, and crop to remove all blank space
20    Zoom,
21}
22
23impl BackgroundMode {
24    fn from_str(string: &str) -> BackgroundMode {
25        match string {
26            "fill" => BackgroundMode::Fill,
27            "scale" => BackgroundMode::Scale,
28            "zoom" => BackgroundMode::Zoom,
29            _ => BackgroundMode::Center
30        }
31    }
32}
33
34fn find_scale(image: &Image, mode: BackgroundMode, display_width: u32, display_height: u32) -> (u32, u32) {
35    match mode {
36        BackgroundMode::Center => {
37            (image.width(), image.height())
38        },
39        BackgroundMode::Fill => {
40            (display_width, display_height)
41        },
42        BackgroundMode::Scale => {
43            let d_w = display_width as f64;
44            let d_h = display_height as f64;
45            let i_w = image.width() as f64;
46            let i_h = image.height() as f64;
47
48            let scale = if d_w / d_h > i_w / i_h {
49                d_h / i_h
50            } else {
51                d_w / i_w
52            };
53
54            ((i_w * scale) as u32, (i_h * scale) as u32)
55        },
56        BackgroundMode::Zoom => {
57            let d_w = display_width as f64;
58            let d_h = display_height as f64;
59            let i_w = image.width() as f64;
60            let i_h = image.height() as f64;
61
62            let scale = if d_w / d_h < i_w / i_h {
63                d_h / i_h
64            } else {
65                d_w / i_w
66            };
67
68            ((i_w * scale) as u32, (i_h * scale) as u32)
69        }
70    }
71}
72
73fn main() {
74    let mut args = env::args().skip(1);
75
76    let path = match args.next() {
77        Some(arg) => arg,
78        None => "/ui/background.png".to_string(),
79    };
80
81    let mode = BackgroundMode::from_str(&args.next().unwrap_or(String::new()));
82
83    match Image::from_path(&path) {
84        Ok(image) => {
85            let (display_width, display_height) = orbclient::get_display_size().expect("background: failed to get display size");
86
87            let mut window = Window::new_flags(
88                0, 0, display_width, display_height, &format!("{} - Background", path),
89                &[WindowFlag::Back, WindowFlag::Borderless, WindowFlag::Unclosable]
90            ).unwrap();
91
92            let mut scaled_image = image.clone();
93            let mut resize = Some((display_width, display_height));
94            loop {
95                if let Some((w, h)) = resize.take() {
96                    let (width, height) = find_scale(&image, mode, w, h);
97
98                    if width == scaled_image.width() && height == scaled_image.height() {
99                        // Do not resize scaled image
100                    } else if width == image.width() && height == image.height() {
101                        scaled_image = image.clone();
102                    } else {
103                        scaled_image = image.resize(width, height, orbimage::ResizeType::Lanczos3).unwrap();
104                    }
105
106                    let (crop_x, crop_w) = if width > w  {
107                        ((width - w)/2, w)
108                    } else {
109                        (0, width)
110                    };
111
112                    let (crop_y, crop_h) = if height > h {
113                        ((height - h)/2, h)
114                    } else {
115                        (0, height)
116                    };
117
118                    window.set(Color::rgb(0, 0, 0));
119
120                    let x = (w as i32 - crop_w as i32)/2;
121                    let y = (h as i32 - crop_h as i32)/2;
122                    scaled_image.roi(
123                        crop_x, crop_y,
124                        crop_w, crop_h,
125                    ).draw(
126                        &mut window,
127                        x, y
128                    );
129
130                    window.sync();
131                }
132
133                for event in window.events() {
134                    match event.to_option() {
135                        EventOption::Resize(resize_event) => {
136                            resize = Some((resize_event.width, resize_event.height));
137                        },
138                        EventOption::Screen(screen_event) => {
139                            window.set_size(screen_event.width, screen_event.height);
140                            resize = Some((screen_event.width, screen_event.height));
141                        },
142                        EventOption::Quit(_) => return,
143                        _ => ()
144                    }
145                }
146            }
147        },
148        Err(err) => {
149            println!("background: error loading {}: {}", path, err);
150        }
151    }
152}