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 Center,
15 Fill,
17 Scale,
19 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 } 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}