summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.toml3
-rw-r--r--source/benoit/benoit.rs1
-rw-r--r--source/benoit/benoit/application.rs11
-rw-r--r--source/benoit/benoit/application/draw.rs2
-rw-r--r--source/benoit/benoit/application/dump.rs8
-rw-r--r--source/benoit/benoit/application/handle_key.rs78
-rw-r--r--source/benoit/benoit/application/initialise.rs31
-rw-r--r--source/benoit/benoit/application/poll_events.rs59
-rw-r--r--source/benoit/benoit/application/render.rs12
-rw-r--r--source/benoit/benoit/configuration.rs39
-rw-r--r--source/benoit/benoit/configuration/load.rs89
13 files changed, 258 insertions, 84 deletions
diff --git a/.gitignore b/.gitignore
index d196ecb..b1f83ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
*.webp
/old
/target
+Benoit.toml
Cargo.lock
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 829e080..5a7560b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+# 17
+
+* Modulise code
+* Check I/O errors
+* Support configuration
+* Depend on toml
+* Update gitignore
+
# 16
* Clean up code
diff --git a/Cargo.toml b/Cargo.toml
index 4690167..b219afd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "benoit"
-version = "0.18.0"
+version = "0.19.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Mandelbrot renderer."
@@ -16,4 +16,5 @@ lto = true
[dependencies]
sdl2 = "0.35.2"
+toml = "0.7.6"
webp = "0.2.5"
diff --git a/source/benoit/benoit.rs b/source/benoit/benoit.rs
index 5b4b9e2..d7deab8 100644
--- a/source/benoit/benoit.rs
+++ b/source/benoit/benoit.rs
@@ -22,3 +22,4 @@
*/
pub mod application;
+pub mod configuration;
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs
index 335d754..f6cb60f 100644
--- a/source/benoit/benoit/application.rs
+++ b/source/benoit/benoit/application.rs
@@ -29,6 +29,7 @@ use sdl2::render::WindowCanvas;
pub mod colour;
pub mod draw;
pub mod dump;
+pub mod handle_key;
pub mod initialise;
pub mod poll_events;
pub mod render_row;
@@ -36,10 +37,6 @@ pub mod render;
pub mod run;
pub struct Application {
- sdl: Sdl,
- sdl_video: VideoSubsystem,
- canvas: WindowCanvas,
-
thread_count: u32,
canvas_width: u32,
@@ -51,5 +48,11 @@ pub struct Application {
zoom: f64,
maximum_iteration_count: u32,
+ dump_path: String,
+
+ sdl: Sdl,
+ sdl_video: VideoSubsystem,
+ canvas: WindowCanvas,
+
do_draw: bool,
}
diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs
index 29e0faf..6cf9196 100644
--- a/source/benoit/benoit/application/draw.rs
+++ b/source/benoit/benoit/application/draw.rs
@@ -33,7 +33,7 @@ impl Application {
let canvas_size = self.canvas_height * self.canvas_width;
let mut data: Vec::<u32> = vec![0x0; canvas_size as usize];
- self.render(&mut data[..]);
+ self.render(&mut data[..], self.position_x, self.position_y, self.zoom, self.maximum_iteration_count);
let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3];
self.colour(&mut image[..], &data[..]);
diff --git a/source/benoit/benoit/application/dump.rs b/source/benoit/benoit/application/dump.rs
index 25ec520..ca658b3 100644
--- a/source/benoit/benoit/application/dump.rs
+++ b/source/benoit/benoit/application/dump.rs
@@ -29,11 +29,11 @@ use std::fs::write;
use webp::Encoder;
impl Application {
- pub fn dump_image(&mut self) {
+ pub fn dump(&mut self, path: String) {
let canvas_size = self.canvas_height * self.canvas_width;
let mut data: Vec::<u32> = vec![0x0; canvas_size as usize];
- self.render(&mut data[..]);
+ self.render(&mut data[..], self.position_x, self.position_y, self.zoom, self.maximum_iteration_count);
let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3];
self.colour(&mut image[..], &data[..]);
@@ -42,8 +42,6 @@ impl Application {
let data = encoder.encode_lossless();
- let file_path = "./image.webp";
-
- write(file_path, &*data);
+ write(path, &*data).expect("unable to write image");
}
}
diff --git a/source/benoit/benoit/application/handle_key.rs b/source/benoit/benoit/application/handle_key.rs
new file mode 100644
index 0000000..e28cef5
--- /dev/null
+++ b/source/benoit/benoit/application/handle_key.rs
@@ -0,0 +1,78 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::application::Application;
+
+extern crate sdl2;
+
+use sdl2::keyboard::Scancode;
+
+impl Application {
+ pub fn handle_key(&mut self, scan_code: Scancode) -> bool {
+ match scan_code {
+ Scancode::Escape => return true,
+ Scancode::X => self.dump(self.dump_path.clone()),
+ _ => {},
+ }
+
+ self.zoom = match scan_code {
+ Scancode::E => self.zoom * 2.0,
+ Scancode::Q => self.zoom / 2.0,
+ _ => self.zoom,
+ };
+
+ let translate_ammount: f64 = 1.0 / 16.0 / self.zoom;
+
+ self.position_x += match scan_code {
+ Scancode::A => -translate_ammount,
+ Scancode::D => translate_ammount,
+ _ => 0.0,
+ };
+
+ self.position_y += match scan_code {
+ Scancode::S => translate_ammount,
+ Scancode::W => -translate_ammount,
+ _ => 0.0,
+ };
+
+ self.maximum_iteration_count = match scan_code {
+ Scancode::F => self.maximum_iteration_count * 0x2,
+ Scancode::R => self.maximum_iteration_count / 0x2,
+ _ => self.maximum_iteration_count,
+ };
+
+ self.do_draw = match scan_code {
+ Scancode::A => true,
+ Scancode::D => true,
+ Scancode::E => true,
+ Scancode::F => true,
+ Scancode::Q => true,
+ Scancode::R => true,
+ Scancode::S => true,
+ Scancode::W => true,
+ _ => false,
+ };
+
+ return false;
+ }
+}
diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs
index 28245b2..3de87e7 100644
--- a/source/benoit/benoit/application/initialise.rs
+++ b/source/benoit/benoit/application/initialise.rs
@@ -22,35 +22,36 @@
*/
use crate::benoit::application::Application;
+use crate::benoit::configuration::Configuration;
impl Application {
pub fn initialise() -> Application {
- let canvas_width: u32 = 0x400;
- let canvas_height: u32 = 0x400;
- let scale: u32 = 0x1;
+ let configuration = Configuration::load("./Benoit.toml");
let sdl = sdl2::init().expect("unable to initialise sdl2");
let sdl_video = sdl.video().expect("unable to initialise video");
- let window = sdl_video.window("Benoit", canvas_width * scale, canvas_height * scale).position_centered().build().expect("unable to open window");
+ let window = sdl_video.window("Benoit", configuration.canvas_width * configuration.scale, configuration.canvas_height * configuration.scale).position_centered().build().expect("unable to open window");
let canvas = window.into_canvas().build().expect("unable to create canvas");
return Application {
- sdl: sdl,
- sdl_video: sdl_video,
- canvas: canvas,
+ thread_count: configuration.thread_count,
+
+ canvas_width: configuration.canvas_width,
+ canvas_height: configuration.canvas_height,
+ scale: configuration.scale,
- thread_count: 0x10,
+ position_x: configuration.position_x,
+ position_y: configuration.position_y,
+ zoom: configuration.zoom,
+ maximum_iteration_count: configuration.maximum_iteration_count,
- canvas_width: canvas_width,
- canvas_height: canvas_height,
- scale: scale,
+ dump_path: configuration.dump_path,
- position_x: 0.0,
- position_y: 0.0,
- zoom: 1.0,
- maximum_iteration_count: 0x100,
+ sdl: sdl,
+ sdl_video: sdl_video,
+ canvas: canvas,
do_draw: true,
};
diff --git a/source/benoit/benoit/application/poll_events.rs b/source/benoit/benoit/application/poll_events.rs
index 42e9c55..e89f003 100644
--- a/source/benoit/benoit/application/poll_events.rs
+++ b/source/benoit/benoit/application/poll_events.rs
@@ -27,69 +27,24 @@ extern crate sdl2;
use sdl2::EventPump;
use sdl2::event::Event;
-use sdl2::keyboard::Scancode;
impl Application {
pub fn poll_events(&mut self, event_pump: &mut EventPump) -> bool {
for event in event_pump.poll_iter() {
- match event {
+ let quit = match event {
Event::KeyDown {
timestamp: _,
window_id: _,
keycode: _,
- scancode,
+ scancode: scan_code,
keymod: _,
repeat: _,
- } => {
- let scancode = scancode.unwrap();
+ } => self.handle_key(scan_code.unwrap()),
+ Event::Quit { .. } => true,
+ _ => false,
+ };
- match scancode {
- Scancode::Escape => return true,
- Scancode::X => self.dump_image(),
- _ => {},
- }
-
- self.zoom = match scancode {
- Scancode::E => self.zoom * 2.0,
- Scancode::Q => self.zoom / 2.0,
- _ => self.zoom,
- };
-
- let translate_ammount: f64 = 1.0 / 16.0 / self.zoom;
-
- self.position_x += match scancode {
- Scancode::A => -translate_ammount,
- Scancode::D => translate_ammount,
- _ => 0.0,
- };
-
- self.position_y += match scancode {
- Scancode::S => translate_ammount,
- Scancode::W => -translate_ammount,
- _ => 0.0,
- };
-
- self.maximum_iteration_count = match scancode {
- Scancode::F => self.maximum_iteration_count * 0x2,
- Scancode::R => self.maximum_iteration_count / 0x2,
- _ => self.maximum_iteration_count,
- };
-
- self.do_draw = match scancode {
- Scancode::A => true,
- Scancode::D => true,
- Scancode::E => true,
- Scancode::F => true,
- Scancode::Q => true,
- Scancode::R => true,
- Scancode::S => true,
- Scancode::W => true,
- _ => false,
- };
- },
- Event::Quit { .. } => return true,
- _ => {},
- }
+ if quit { return true }
}
return false;
diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs
index becf95b..df14024 100644
--- a/source/benoit/benoit/application/render.rs
+++ b/source/benoit/benoit/application/render.rs
@@ -29,8 +29,8 @@ use std::time::Instant;
use std::ptr::addr_of_mut;
impl Application {
- pub fn render(&mut self, buffer: &mut [u32]) {
- eprintln!("rendering: {}{:+}i ({}x) @ ({})", self.position_x, self.position_y, self.zoom, self.maximum_iteration_count);
+ pub fn render(&mut self, buffer: &mut [u32], position_x: f64, position_y: f64, zoom: f64, maximum_iteration_count: u32) {
+ eprintln!("rendering: {}{:+}i ({}x) @ ({})", position_x, position_y, zoom, maximum_iteration_count);
let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize);
@@ -46,10 +46,10 @@ impl Application {
let canvas_width = self.canvas_width;
let canvas_height = self.canvas_height;
- let position_x = self.position_x;
- let position_y = self.position_y;
- let zoom = self.zoom;
- let maximum_iteration_count = self.maximum_iteration_count;
+ let position_x = position_x;
+ let position_y = position_y;
+ let zoom = zoom;
+ let maximum_iteration_count = maximum_iteration_count;
let mut y: u32 = 0x0;
diff --git a/source/benoit/benoit/configuration.rs b/source/benoit/benoit/configuration.rs
new file mode 100644
index 0000000..f7c19e0
--- /dev/null
+++ b/source/benoit/benoit/configuration.rs
@@ -0,0 +1,39 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+pub mod load;
+
+pub struct Configuration {
+ pub thread_count: u32,
+
+ pub canvas_width: u32,
+ pub canvas_height: u32,
+ pub scale: u32,
+
+ pub position_x: f64,
+ pub position_y: f64,
+ pub zoom: f64,
+ pub maximum_iteration_count: u32,
+
+ pub dump_path: String,
+}
diff --git a/source/benoit/benoit/configuration/load.rs b/source/benoit/benoit/configuration/load.rs
new file mode 100644
index 0000000..51db6b1
--- /dev/null
+++ b/source/benoit/benoit/configuration/load.rs
@@ -0,0 +1,89 @@
+/*
+ Copyright 2021, 2023 Gabriel Bjørnager Jensen.
+
+ This file is part of Benoit.
+
+ Benoit is free software: you can redistribute it
+ and/or modify it under the terms of the GNU
+ Affero General Public License as published by
+ the Free Software Foundation, either version 3
+ of the License, or (at your option) any later
+ version.
+
+ Benoit is distributed in the hope that it will
+ be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU
+ Affero General Public License along with Benoit.
+ If not, see <https://www.gnu.org/licenses/>.
+*/
+
+use crate::benoit::configuration::Configuration;
+
+extern crate toml;
+
+use std::fs::read;
+use std::str::FromStr;
+use toml::{Table, Value};
+
+impl Configuration {
+ pub fn load(path: &str) -> Configuration {
+ let mut configuration = Configuration {
+ thread_count: 0x2,
+
+ canvas_width: 0x100,
+ canvas_height: 0x100,
+ scale: 0x1,
+
+ position_x: 0.0,
+ position_y: 0.0,
+ zoom: 1.0,
+ maximum_iteration_count: 0x100,
+
+ dump_path: "./image.webp".to_string(),
+ };
+
+ let configuration_text = match read(path) {
+ Ok(content) => String::from_utf8_lossy(&content).to_string(),
+ Err(..) => {
+ eprintln!("unable to read configuration file");
+ return configuration;
+ },
+ };
+
+ let configuration_table = Table::from_str(configuration_text.as_str()).expect("unable to parse configuration");
+
+ let get_integer = |buffer: &mut u32, table: &Table, name: &str| {
+ if !table.contains_key(name) { return }
+
+ match configuration_table[name] {
+ Value::Integer(value) => *buffer = value as u32,
+ _ => panic!("mismatched type for {name}"),
+ };
+ };
+
+ let get_float = |buffer: &mut f64, table: &Table, name: &str| {
+ if !table.contains_key(name) { return }
+
+ match configuration_table[name] {
+ Value::Float(value) => *buffer = value,
+ _ => panic!("mismatched type for {name}"),
+ };
+ };
+
+ get_integer(&mut configuration.canvas_width, &configuration_table, "canvas_width");
+ get_integer(&mut configuration.canvas_height, &configuration_table, "canvas_height");
+ get_integer(&mut configuration.scale, &configuration_table, "scale");
+
+ get_float(&mut configuration.position_x, &configuration_table, "position_x");
+ get_float(&mut configuration.position_y, &configuration_table, "position_y");
+ get_float(&mut configuration.zoom, &configuration_table, "zoom");
+
+ get_integer(&mut configuration.maximum_iteration_count, &configuration_table, "maximum_iteration_count");
+
+ return configuration;
+ }
+}