use core::slice::ChunksMut;
use sdl2::{
pixels::Color,
pixels::PixelFormatEnum,
render::Texture,
render::WindowCanvas
};
use crate::base::{
PROG_TITLE,
PrependErrorString
};
use super::config::Config;
mod geom;
mod image;
mod pixel;
mod text;
pub use self::image::Image;
pub struct System {
width: i32,
height: i32,
buffer: Vec<u8>,
sdl_screen_canvas: WindowCanvas,
sdl_screen_texture: Texture, }
impl System {
pub fn init(sdl: &sdl2::Sdl, config: &Config) -> Result<System, String> {
let video_subsystem = sdl.video().pre_err("cannot init sdl video")?;
video_subsystem.disable_screen_saver();
let width = if config.width > 0 {config.width} else {video_subsystem.current_display_mode(0)?.w};
let height = if config.height > 0 {config.height} else {video_subsystem.current_display_mode(0)?.h};
if (width & 1) != 0 {
return Err(format!("screen width {} is not even", width));
}
if (height & 1) != 0 {
return Err(format!("screen height {} is not even", height));
}
let buffer: Vec<u8> = vec![0xFF; ((width as usize) * (height as usize)) << 2];
let mut window_builder = video_subsystem.window(PROG_TITLE, width as u32, height as u32);
if (config.width <= 0) && (config.height <= 0) {
window_builder.fullscreen();
}
let window = window_builder.build().pre_err("cannot build sdl window")?;
let mut canvas_builder = window.into_canvas();
if config.vsync {
canvas_builder = canvas_builder.present_vsync();
}
let mut sdl_screen_canvas = canvas_builder.build().pre_err("cannot build sdl canvas")?;
sdl_screen_canvas.set_draw_color(Color::RGB(0, 0, 0));
sdl_screen_canvas.clear();
sdl_screen_canvas.present();
let sdl_texture_creator = sdl_screen_canvas.texture_creator();
let sdl_screen_texture = sdl_texture_creator.create_texture_streaming(Some(PixelFormatEnum::ARGB8888), width as u32, height as u32)
.pre_err("cannot create sdl texture")?;
Ok(System{width, height, buffer, sdl_screen_canvas, sdl_screen_texture})
}
pub fn width(&self) -> i32 {
self.width
}
pub fn height(&self) -> i32 {
self.height
}
pub fn show(&mut self) -> Result<(), String> {
self.sdl_screen_texture.update(None, &self.buffer, (self.width as usize) << 2)
.pre_err("cannot update sdl texture from buffer")?;
self.sdl_screen_canvas.copy(&self.sdl_screen_texture, None, None).pre_err("cannot copy sdl texture to sdl canvas")?;
self.sdl_screen_canvas.present();
Ok(())
}
pub fn clear(&mut self) {
self.buffer.fill(0);
}
pub fn screen_raw_mut(&mut self) -> &mut [u8] {
&mut self.buffer
}
pub fn screen_raw_chunks_mut(&mut self, pixels_per_chunk: i32) -> ChunksMut<'_, u8> {
self.buffer.chunks_mut((pixels_per_chunk << 2) as usize)
}
pub fn shut(&mut self) -> Result<(), String> {
Ok(())
}
}