lines, barebones drawing window
addition of lines means ipc slightly changed, though can be ignored. also, minor malvim fix
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ming-wm"
|
name = "ming-wm"
|
||||||
version = "1.1.0"
|
version = "1.2.0-beta.0"
|
||||||
repository = "https://github.com/stjet/ming-wm"
|
repository = "https://github.com/stjet/ming-wm"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@@ -63,3 +63,7 @@ path = "src/bin/malvim.rs"
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mingGames_Reversi"
|
name = "mingGames_Reversi"
|
||||||
path = "src/bin/reversi.rs"
|
path = "src/bin/reversi.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "mingUtils_Draw"
|
||||||
|
path = "src/bin/draw.rs"
|
||||||
14
docs/window-likes/draw.md
Normal file
14
docs/window-likes/draw.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Very basic drawing board.
|
||||||
|
|
||||||
|
## Moving
|
||||||
|
|
||||||
|
Arrow keys or hjkl. `i` to enter input mode. Use the enter key to finish a line or rectangle. Escape to cancel line or rectangle in progress.
|
||||||
|
|
||||||
|
## Input Commands
|
||||||
|
|
||||||
|
- `line`: Start line with current point as start. Move and hit enter to determine line endpoint
|
||||||
|
- `rect`: Start rect with current point as a corner. Move and hit enter to determine the opposite corner
|
||||||
|
- `color/c/colour [lowercase 6 char hex string]`: Set current colour
|
||||||
|
- `linewidth/lw [int]`: Set current line width
|
||||||
|
- `undo`: Undo last draw
|
||||||
|
- `clear`: Clear all drawings
|
||||||
1
install
1
install
@@ -16,3 +16,4 @@ cp ./target/release/mingGames_Minesweeper /usr/local/bin/mingGames_Minesweeper
|
|||||||
cp ./target/release/mingFiles_File_Explorer /usr/local/bin/mingFiles_File_Explorer
|
cp ./target/release/mingFiles_File_Explorer /usr/local/bin/mingFiles_File_Explorer
|
||||||
cp ./target/release/mingFiles_Audio_Player /usr/local/bin/mingFiles_Audio_Player
|
cp ./target/release/mingFiles_Audio_Player /usr/local/bin/mingFiles_Audio_Player
|
||||||
cp ./target/release/mingEditing_Malvim /usr/local/bin/mingEditing_Malvim
|
cp ./target/release/mingEditing_Malvim /usr/local/bin/mingEditing_Malvim
|
||||||
|
cp ./target/release/mingUtils_Draw /usr/local/bin/mingUtils_Draw
|
||||||
|
|||||||
@@ -16,3 +16,4 @@ cp ./target/release/mingGames_Minesweeper ~/.local/bin/mingGames_Minesweeper
|
|||||||
cp ./target/release/mingFiles_File_Explorer ~/.local/bin/mingFiles_File_Explorer
|
cp ./target/release/mingFiles_File_Explorer ~/.local/bin/mingFiles_File_Explorer
|
||||||
cp ./target/release/mingFiles_Audio_Player ~/.local/bin/mingFiles_Audio_Player
|
cp ./target/release/mingFiles_Audio_Player ~/.local/bin/mingFiles_Audio_Player
|
||||||
cp ./target/release/mingEditing_Malvim ~/.local/bin/mingEditing_Malvim
|
cp ./target/release/mingEditing_Malvim ~/.local/bin/mingEditing_Malvim
|
||||||
|
cp ./target/release/mingUtils_Draw ~/.local/bin/mingUtils_Draw
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ impl Serializable for DrawInstructions {
|
|||||||
DrawInstructions::Gradient(p, d, c1, c2, u) => format!("Gradient/{}\x1E{}\x1E{}\x1E{}\x1E{}", array_to_string(p), array_to_string(d), array_to_string(c1), array_to_string(c2), u),
|
DrawInstructions::Gradient(p, d, c1, c2, u) => format!("Gradient/{}\x1E{}\x1E{}\x1E{}\x1E{}", array_to_string(p), array_to_string(d), array_to_string(c1), array_to_string(c2), u),
|
||||||
DrawInstructions::Bmp(p, s, b) => format!("Bmp/{}\x1E{}\x1E{}", array_to_string(p), s, b),
|
DrawInstructions::Bmp(p, s, b) => format!("Bmp/{}\x1E{}\x1E{}", array_to_string(p), s, b),
|
||||||
DrawInstructions::Circle(p, u, c) => format!("Circle/{}\x1E{}\x1E{}", array_to_string(p), u, array_to_string(c)),
|
DrawInstructions::Circle(p, u, c) => format!("Circle/{}\x1E{}\x1E{}", array_to_string(p), u, array_to_string(c)),
|
||||||
|
DrawInstructions::Line(s, e, w, c) => format!("Line/{}\x1E{}\x1E{}\x1E{}", array_to_string(s), array_to_string(e), w, array_to_string(c)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn deserialize(serialized: &str) -> Result<Self, ()> {
|
fn deserialize(serialized: &str) -> Result<Self, ()> {
|
||||||
@@ -402,6 +403,35 @@ impl Serializable for DrawInstructions {
|
|||||||
let c = get_color(arg.unwrap())?;
|
let c = get_color(arg.unwrap())?;
|
||||||
Ok(DrawInstructions::Circle(p, u.unwrap(), c))
|
Ok(DrawInstructions::Circle(p, u.unwrap(), c))
|
||||||
},
|
},
|
||||||
|
"Line" => {
|
||||||
|
let rest = get_rest_of_split(&mut parts, Some("/"));
|
||||||
|
//(s, e, w, c)
|
||||||
|
let mut args = rest.split("\x1E");
|
||||||
|
let arg = args.next();
|
||||||
|
if arg.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let s = get_two_array(arg.unwrap())?;
|
||||||
|
let arg = args.next();
|
||||||
|
if arg.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let e = get_two_array(arg.unwrap())?;
|
||||||
|
let arg = args.next();
|
||||||
|
if arg.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let w = arg.unwrap().parse();
|
||||||
|
if w.is_err() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let arg = args.next();
|
||||||
|
if arg.is_none() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let c = get_color(arg.unwrap())?;
|
||||||
|
Ok(DrawInstructions::Line(s, e, w.unwrap(), c))
|
||||||
|
},
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,18 @@ pub enum KeyChar {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DrawInstructions {
|
pub enum DrawInstructions {
|
||||||
|
/// Top left point, dimensions, colour
|
||||||
Rect(Point, Dimensions, RGBColor),
|
Rect(Point, Dimensions, RGBColor),
|
||||||
Text(Point, Vec<String>, String, RGBColor, RGBColor, Option<usize>, Option<u8>), //font and text
|
/// Top left point, fonts, text, colour, background colour, horizontal spacing, monospace width
|
||||||
|
Text(Point, Vec<String>, String, RGBColor, RGBColor, Option<usize>, Option<u8>),
|
||||||
|
/// Top left point, dimensions, start colour, end colour, steps
|
||||||
Gradient(Point, Dimensions, RGBColor, RGBColor, usize),
|
Gradient(Point, Dimensions, RGBColor, RGBColor, usize),
|
||||||
|
/// Top left point, path to file, reverse
|
||||||
Bmp(Point, String, bool),
|
Bmp(Point, String, bool),
|
||||||
|
/// Centre point, radius, colour
|
||||||
Circle(Point, usize, RGBColor),
|
Circle(Point, usize, RGBColor),
|
||||||
|
/// Start point, end point, line width, line colour
|
||||||
|
Line(Point, Point, usize, RGBColor),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
|||||||
235
src/bin/draw.rs
Normal file
235
src/bin/draw.rs
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
use std::vec::Vec;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
|
use ming_wm_lib::window_manager_types::{ DrawInstructions, WindowLike, WindowLikeType };
|
||||||
|
use ming_wm_lib::messages::{ WindowMessage, WindowMessageResponse };
|
||||||
|
use ming_wm_lib::framebuffer_types::{ Dimensions, Point, RGBColor };
|
||||||
|
use ming_wm_lib::themes::ThemeInfo;
|
||||||
|
use ming_wm_lib::utils::{ hex_to_u8, HEX_CHARS, Substring };
|
||||||
|
use ming_wm_lib::ipc::listen;
|
||||||
|
|
||||||
|
enum DrawAction {
|
||||||
|
Line(Point, Option<Point>, usize, RGBColor),
|
||||||
|
Rect(Point, Option<Dimensions>, RGBColor),
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrawAction {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
match self {
|
||||||
|
DrawAction::Line(_, _, _, _) => "Line",
|
||||||
|
DrawAction::Rect(_, _, _) => "Rect",
|
||||||
|
}.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq)]
|
||||||
|
enum Mode {
|
||||||
|
#[default]
|
||||||
|
Move,
|
||||||
|
Input,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Draw {
|
||||||
|
mode: Mode,
|
||||||
|
dimensions: Dimensions,
|
||||||
|
draw_actions: Vec<DrawAction>,
|
||||||
|
current_location: Point,
|
||||||
|
current_input: String,
|
||||||
|
current_color: RGBColor,
|
||||||
|
current_linewidth: usize,
|
||||||
|
current_action: Option<DrawAction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowLike for Draw {
|
||||||
|
fn handle_message(&mut self, message: WindowMessage) -> WindowMessageResponse {
|
||||||
|
match message {
|
||||||
|
WindowMessage::Init(dimensions) => {
|
||||||
|
self.dimensions = dimensions;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
},
|
||||||
|
WindowMessage::KeyPress(key_press) => {
|
||||||
|
if key_press.is_escape() && (self.current_action.is_some() || self.mode != Mode::Move) {
|
||||||
|
self.current_action = None;
|
||||||
|
self.mode = Mode::Move;
|
||||||
|
self.current_input = String::new();
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else if self.mode == Mode::Input {
|
||||||
|
if key_press.is_backspace() && self.current_input.len() > 0 {
|
||||||
|
self.current_input = self.current_input.remove_last();
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else if key_press.is_enter() {
|
||||||
|
//process current input
|
||||||
|
let mut parts = self.current_input.split(" ");
|
||||||
|
match parts.next().unwrap() {
|
||||||
|
"line" | "l" => {
|
||||||
|
self.current_action = Some(DrawAction::Line(self.current_location, None, self.current_linewidth, self.current_color));
|
||||||
|
},
|
||||||
|
"rect" | "r" => {
|
||||||
|
self.current_action = Some(DrawAction::Rect(self.current_location, None, self.current_color));
|
||||||
|
},
|
||||||
|
"colour" | "color" | "c" => {
|
||||||
|
//hex to u8
|
||||||
|
if let Some(hex_color) = parts.next() {
|
||||||
|
if hex_color.len() == 6 && hex_color.chars().all(|c| HEX_CHARS.contains(&c)) {
|
||||||
|
let mut hex_chars = hex_color.chars();
|
||||||
|
self.current_color = [hex_to_u8(hex_chars.next().unwrap(), hex_chars.next().unwrap()), hex_to_u8(hex_chars.next().unwrap(), hex_chars.next().unwrap()), hex_to_u8(hex_chars.next().unwrap(), hex_chars.next().unwrap())];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linewidth" | "lw" => {
|
||||||
|
if let Ok(linewidth) = parts.next().unwrap_or("").parse::<usize>() {
|
||||||
|
self.current_linewidth = linewidth;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"undo" | "u" => {
|
||||||
|
self.draw_actions.pop();
|
||||||
|
},
|
||||||
|
"clear" | "cl" => {
|
||||||
|
self.draw_actions = Vec::new();
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
self.mode = Mode::Move;
|
||||||
|
self.current_input = String::new();
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else if key_press.is_regular() {
|
||||||
|
self.current_input += &key_press.key.to_string();
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else if key_press.key == 'i' && self.current_action.is_none() {
|
||||||
|
self.mode = Mode::Input;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else if key_press.is_enter() {
|
||||||
|
if let Some(current_action) = &self.current_action {
|
||||||
|
self.draw_actions.push(match current_action {
|
||||||
|
DrawAction::Line(p, _, u, r) => DrawAction::Line(*p, Some(self.current_location), *u, *r),
|
||||||
|
DrawAction::Rect(p, _, r) => {
|
||||||
|
let d = [
|
||||||
|
if self.current_location[0] > p[0] {
|
||||||
|
self.current_location[0] - p[0]
|
||||||
|
} else {
|
||||||
|
p[0] - self.current_location[0]
|
||||||
|
},
|
||||||
|
if self.current_location[1] > p[1] {
|
||||||
|
self.current_location[1] - p[1]
|
||||||
|
} else {
|
||||||
|
p[1] - self.current_location[1]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
//find top left corner
|
||||||
|
let tl = [
|
||||||
|
if p[0] < self.current_location[0] {
|
||||||
|
p[0]
|
||||||
|
} else {
|
||||||
|
self.current_location[0]
|
||||||
|
},
|
||||||
|
if p[1] < self.current_location[1] {
|
||||||
|
p[1]
|
||||||
|
} else {
|
||||||
|
self.current_location[1]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
DrawAction::Rect(tl, Some(d), *r)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
self.current_action = None;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else if key_press.is_up_arrow() || key_press.key == 'k' {
|
||||||
|
if self.current_location[1] > 0 {
|
||||||
|
self.current_location[1] -= 1;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else if key_press.is_down_arrow() || key_press.key == 'j' {
|
||||||
|
if self.current_location[1] + 1 < self.dimensions[1] {
|
||||||
|
self.current_location[1] += 1;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else if key_press.is_left_arrow() || key_press.key == 'h' {
|
||||||
|
if self.current_location[0] > 0 {
|
||||||
|
self.current_location[0] -= 1;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else if key_press.is_right_arrow() || key_press.key == 'l' {
|
||||||
|
if self.current_location[0] + 1 < self.dimensions[0] {
|
||||||
|
self.current_location[0] += 1;
|
||||||
|
WindowMessageResponse::JustRedraw
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WindowMessageResponse::DoNothing
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => WindowMessageResponse::DoNothing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
//draw previous actions
|
||||||
|
for action in &self.draw_actions {
|
||||||
|
instructions.push(match action {
|
||||||
|
DrawAction::Line(p1, p2, lw, c) => DrawInstructions::Line(*p1, p2.unwrap(), *lw, *c),
|
||||||
|
DrawAction::Rect(p, d, c) => DrawInstructions::Rect(*p, d.unwrap(), *c),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//draw cursor (crosshair)
|
||||||
|
let crosshair_min_x = self.current_location[0].checked_sub(6).unwrap_or(0);
|
||||||
|
let crosshair_min_y = self.current_location[1].checked_sub(6).unwrap_or(0);
|
||||||
|
//^going over should be handled by the drawer, probably?
|
||||||
|
instructions.push(DrawInstructions::Line([crosshair_min_x, self.current_location[1]], [self.current_location[0] + 6, self.current_location[1]], 1, self.current_color));
|
||||||
|
instructions.push(DrawInstructions::Line([self.current_location[0], crosshair_min_y], [self.current_location[0], self.current_location[1] + 6], 1, self.current_color));
|
||||||
|
//draw info or current input
|
||||||
|
instructions.push(DrawInstructions::Text([2, self.dimensions[1] - 19], vec!["nimbus-roman".to_string()], if self.current_input == String::new() {
|
||||||
|
if let Some(current_action) = &self.current_action {
|
||||||
|
current_action.name()
|
||||||
|
} else if self.mode == Mode::Move {
|
||||||
|
"'i' to enter input mode".to_string()
|
||||||
|
} else {
|
||||||
|
"Awaiting input".to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.current_input.clone()
|
||||||
|
}, theme_info.text, theme_info.background, None, None));
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
//properties
|
||||||
|
|
||||||
|
fn title(&self) -> String {
|
||||||
|
"Draw".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subtype(&self) -> WindowLikeType {
|
||||||
|
WindowLikeType::Window
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ideal_dimensions(&self, _dimensions: Dimensions) -> Dimensions {
|
||||||
|
[410, 410]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Draw {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut d: Self = Default::default();
|
||||||
|
d.current_linewidth = 1;
|
||||||
|
d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
listen(Draw::new());
|
||||||
|
}
|
||||||
@@ -168,11 +168,14 @@ impl WindowLike for Malvim {
|
|||||||
self.state = State::None;
|
self.state = State::None;
|
||||||
} else if self.state == State::MaybeDelete {
|
} else if self.state == State::MaybeDelete {
|
||||||
if key_press.key == 'd' {
|
if key_press.key == 'd' {
|
||||||
|
for _ in 0..self.maybe_num.unwrap_or(1) {
|
||||||
current_file.content.remove(current_file.line_pos);
|
current_file.content.remove(current_file.line_pos);
|
||||||
if current_file.content.len() == 0 {
|
if current_file.content.len() == 0 {
|
||||||
current_file.content = vec![String::new()];
|
current_file.content = vec![String::new()];
|
||||||
} else if current_file.line_pos == current_file.content.len() {
|
} else if current_file.line_pos == current_file.content.len() {
|
||||||
current_file.line_pos = current_file.content.len() - 1;
|
current_file.line_pos = current_file.content.len() - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let new_length = current_file.content[current_file.line_pos].chars().count();
|
let new_length = current_file.content[current_file.line_pos].chars().count();
|
||||||
current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length);
|
current_file.cursor_pos = calc_new_cursor_pos(current_file.cursor_pos, new_length);
|
||||||
@@ -392,7 +395,7 @@ impl WindowLike for Malvim {
|
|||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
//reset maybe_num if not num
|
//reset maybe_num if not num
|
||||||
if !numbered && self.state != State::Maybeg {
|
if !numbered && self.state != State::Maybeg && self.state != State::MaybeDelete {
|
||||||
self.maybe_num = None;
|
self.maybe_num = None;
|
||||||
}
|
}
|
||||||
} else if self.mode == Mode::Command {
|
} else if self.mode == Mode::Command {
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ impl FramebufferWriter {
|
|||||||
.copy_from_slice(&color[..]);
|
.copy_from_slice(&color[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//straight horizontal line
|
||||||
fn _draw_line(&mut self, start_pos: usize, bytes: &[u8]) {
|
fn _draw_line(&mut self, start_pos: usize, bytes: &[u8]) {
|
||||||
self.buffer[start_pos..(start_pos + bytes.len())]
|
self.buffer[start_pos..(start_pos + bytes.len())]
|
||||||
.copy_from_slice(bytes);
|
.copy_from_slice(bytes);
|
||||||
@@ -244,6 +245,34 @@ impl FramebufferWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//line
|
||||||
|
|
||||||
|
pub fn draw_line(&mut self, start: Point, end: Point, width: usize, color: RGBColor) {
|
||||||
|
//leftmost point
|
||||||
|
let lm;
|
||||||
|
let rm;
|
||||||
|
if start[0] < end[0] || (start[0] == end[0] && end[1] > start[1]) {
|
||||||
|
lm = start;
|
||||||
|
rm = end;
|
||||||
|
} else {
|
||||||
|
lm = end;
|
||||||
|
rm = start;
|
||||||
|
};
|
||||||
|
let dx = (rm[0] - lm[0]) as f64; //will not be negative
|
||||||
|
let dy = rm[1] as f64 - lm[1] as f64; //surely no point will be big enough to lose data here?
|
||||||
|
let use_x = dy.abs() < dx;
|
||||||
|
//slope
|
||||||
|
let m = if use_x { dy / dx } else { dx / dy };
|
||||||
|
for ci in 0..if use_x { dx as usize } else { dy.abs() as usize } {
|
||||||
|
let i = if !use_x && dy < 0.0 { -(ci as f64) } else { ci as f64 };
|
||||||
|
let ix = if use_x { i } else { (m * i).round() };
|
||||||
|
let iy = if use_x { (m * i).round() } else { i };
|
||||||
|
for j in 0..width {
|
||||||
|
self.draw_pixel([(lm[0] as f64 + ix) as usize + j, (lm[1] as f64 + iy) as usize], color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//bmps
|
//bmps
|
||||||
|
|
||||||
//reverse is workaround for when my bmp lib returns rgba instead of bgra
|
//reverse is workaround for when my bmp lib returns rgba instead of bgra
|
||||||
|
|||||||
@@ -648,6 +648,13 @@ impl WindowManager {
|
|||||||
[top_left[0], top_left[1] + if is_window { WINDOW_TOP_HEIGHT } else { 0 }]
|
[top_left[0], top_left[1] + if is_window { WINDOW_TOP_HEIGHT } else { 0 }]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prevent_overflow_dimensions(dimensions: Dimensions, window_dimensions: Dimensions, top_left: Point) -> Dimensions {
|
||||||
|
[
|
||||||
|
min(dimensions[0], window_dimensions[0] - top_left[0]),
|
||||||
|
min(dimensions[1], window_dimensions[1] - top_left[1]),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
//another issue with a huge vector of draw instructions; it takes up heap memory
|
//another issue with a huge vector of draw instructions; it takes up heap memory
|
||||||
pub fn draw(&mut self, maybe_redraw_ids: Option<Vec<usize>>, use_saved_buffer: bool) {
|
pub fn draw(&mut self, maybe_redraw_ids: Option<Vec<usize>>, use_saved_buffer: bool) {
|
||||||
let theme_info = get_theme_info(&self.theme).unwrap();
|
let theme_info = get_theme_info(&self.theme).unwrap();
|
||||||
@@ -694,6 +701,7 @@ impl WindowManager {
|
|||||||
DrawInstructions::Text(top_left, fonts, text, color, bg_color, horiz_spacing, mono_width) => DrawInstructions::Text(WindowManager::get_true_top_left(top_left, is_window), fonts.clone(), text.clone(), *color, *bg_color, *horiz_spacing, *mono_width),
|
DrawInstructions::Text(top_left, fonts, text, color, bg_color, horiz_spacing, mono_width) => DrawInstructions::Text(WindowManager::get_true_top_left(top_left, is_window), fonts.clone(), text.clone(), *color, *bg_color, *horiz_spacing, *mono_width),
|
||||||
DrawInstructions::Bmp(top_left, path, reverse) => DrawInstructions::Bmp(WindowManager::get_true_top_left(top_left, is_window), path.to_string(), *reverse),
|
DrawInstructions::Bmp(top_left, path, reverse) => DrawInstructions::Bmp(WindowManager::get_true_top_left(top_left, is_window), path.to_string(), *reverse),
|
||||||
DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => DrawInstructions::Gradient(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *start_color, *end_color, *steps),
|
DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => DrawInstructions::Gradient(WindowManager::get_true_top_left(top_left, is_window), *dimensions, *start_color, *end_color, *steps),
|
||||||
|
DrawInstructions::Line(start, end, width, color) => DrawInstructions::Line(WindowManager::get_true_top_left(start, is_window), WindowManager::get_true_top_left(end, is_window), *width, *color),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
//draw window background
|
//draw window background
|
||||||
@@ -729,10 +737,7 @@ impl WindowManager {
|
|||||||
match instruction {
|
match instruction {
|
||||||
DrawInstructions::Rect(top_left, dimensions, color) => {
|
DrawInstructions::Rect(top_left, dimensions, color) => {
|
||||||
//try and prevent overflows out of the window
|
//try and prevent overflows out of the window
|
||||||
let true_dimensions = [
|
let true_dimensions = WindowManager::prevent_overflow_dimensions(dimensions, window_dimensions, top_left);
|
||||||
min(dimensions[0], window_dimensions[0] - top_left[0]),
|
|
||||||
min(dimensions[1], window_dimensions[1] - top_left[1]),
|
|
||||||
];
|
|
||||||
window_writer.draw_rect(top_left, true_dimensions, color);
|
window_writer.draw_rect(top_left, true_dimensions, color);
|
||||||
},
|
},
|
||||||
DrawInstructions::Circle(centre, radius, color) => {
|
DrawInstructions::Circle(centre, radius, color) => {
|
||||||
@@ -746,7 +751,11 @@ impl WindowManager {
|
|||||||
window_writer.draw_bmp(top_left, path, reverse);
|
window_writer.draw_bmp(top_left, path, reverse);
|
||||||
},
|
},
|
||||||
DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => {
|
DrawInstructions::Gradient(top_left, dimensions, start_color, end_color, steps) => {
|
||||||
window_writer.draw_gradient(top_left, dimensions, start_color, end_color, steps);
|
let true_dimensions = WindowManager::prevent_overflow_dimensions(dimensions, window_dimensions, top_left);
|
||||||
|
window_writer.draw_gradient(top_left, true_dimensions, start_color, end_color, steps);
|
||||||
|
},
|
||||||
|
DrawInstructions::Line(start, end, width, color) => {
|
||||||
|
window_writer.draw_line(start, end, width, color);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user