From bbfca639547fcd08e51181b70e449e71281d1d9b Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 28 Mar 2021 09:51:26 +0530 Subject: add new brush type --- src/brush.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lisp/error.rs | 2 ++ src/lisp/eval.rs | 1 + src/lisp/expr.rs | 1 + src/lisp/prelude.rs | 21 ++++++++++++++- src/main.rs | 1 + 6 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/brush.rs diff --git a/src/brush.rs b/src/brush.rs new file mode 100644 index 0000000..98c2b23 --- /dev/null +++ b/src/brush.rs @@ -0,0 +1,73 @@ +use std::fmt; + +use crate::bitmap::MapPoint; + +#[derive(Debug, Copy, Clone)] +pub enum Brush { + Line { + size: u8, + start: Option, + extend: bool, + }, + Circle { + size: u8, + }, + RectSelect { + start: MapPoint, + end: MapPoint, + }, + Fill, + Custom { + size: u8, + }, +} + +impl Brush { + pub fn grow(&mut self) -> Result<(), BrushError> { + match self { + Brush::Line { ref mut size, .. } => *size += 1, + Brush::Circle { ref mut size, .. } => *size += 1, + Brush::Custom { ref mut size, .. } => *size += 1, + _ => return Err(BrushError::CannotIncreaseSize), + } + Ok(()) + } + pub fn shrink(&mut self) -> Result<(), BrushError> { + match self { + Brush::Line { ref mut size, .. } => *size += size.saturating_sub(1), + Brush::Circle { ref mut size, .. } => *size += size.saturating_sub(1), + Brush::Custom { ref mut size, .. } => *size += size.saturating_sub(1), + _ => return Err(BrushError::CannotIncreaseSize), + } + Ok(()) + } + pub fn new() -> Self { + Brush::Circle { size: 0 } + } + pub fn line(size: u8, extend: bool) -> Self { + Brush::Line { + size, + start: None, + extend, + } + } + pub fn is_line(&self) -> bool { + matches!(self, Self::Line { .. }) + } +} + +impl fmt::Display for Brush { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Brush::Line { extend, .. } => write!(f, "LINE{}", if *extend { "+" } else { "" }), + Brush::Circle { .. } => write!(f, "CIRCLE"), + Brush::RectSelect { .. } => write!(f, "SELECT"), + Brush::Fill => write!(f, "FILL"), + Brush::Custom { .. } => write!(f, "CUSTOM"), + } + } +} + +pub enum BrushError { + CannotIncreaseSize, +} diff --git a/src/lisp/error.rs b/src/lisp/error.rs index b90e211..a360eb2 100644 --- a/src/lisp/error.rs +++ b/src/lisp/error.rs @@ -90,6 +90,7 @@ pub enum EvalError { DivByZero, TypeMismatch, NoFileName, + CustomInternal(&'static str), } impl fmt::Display for EvalError { @@ -112,6 +113,7 @@ impl fmt::Display for EvalError { Self::TypeMismatch => write!(f, "mismatched types"), Self::DivByZero => write!(f, "attempt to divide by zero"), Self::NoFileName => write!(f, "no file name specified"), + Self::CustomInternal(s) => write!(f, "{}", s), } } } diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 370b624..6ffff23 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs @@ -20,6 +20,7 @@ pub fn eval(expr: &LispExpr, app: &mut AppState) -> Result LispExpr::Number(_) => Ok(expr.clone()), LispExpr::BoolLit(_) => Ok(expr.clone()), LispExpr::Ident(ref id) => lookup_extended(&app.lisp_env, id), + LispExpr::Quote(_, _) => Ok(expr.clone()), LispExpr::List(li) => { let func_expr = &li[0]; match func_expr { diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs index 40420a1..9ef9f65 100644 --- a/src/lisp/expr.rs +++ b/src/lisp/expr.rs @@ -222,6 +222,7 @@ impl AsRef for LispExpr { fn as_ref(&self) -> &str { match self { LispExpr::StringLit(i) => &i, + LispExpr::Ident(i) => &i, _ => panic!("invalid downcast!"), } } diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index 6153e4f..d2a6ae6 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs @@ -1,7 +1,8 @@ use crate::{ + brush::Brush, lisp::{ error::{EvalError, LispError}, - expr::{Arity, LispExpr}, + expr::{is_ident, Arity, LispExpr}, number::LispNumber, Environment, }, @@ -193,5 +194,23 @@ pub fn new_env() -> Environment { return Ok(LispExpr::Unit); }); + primitive!(env, Arity::Atmost(1), "brush", |args, app| { + info!("brush {}", &args[0]); + if let [LispExpr::Quote(kind, _)] = args { + if is_ident(kind) { + match (&**kind).as_ref() { + "fill" => app.brush = Brush::Fill, + "circle" => app.brush = Brush::new(), + "line" => app.brush = Brush::line(0, false), + "line-extend" => app.brush = Brush::line(0, true), + _ => return Err(EvalError::CustomInternal("unknown brush type").into()), + } + } + } else { + return Err(EvalError::TypeMismatch.into()); + } + return Ok(LispExpr::Unit); + }); + env } diff --git a/src/main.rs b/src/main.rs index 1ecad69..34f087a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod app; mod bitmap; +mod brush; mod command; mod consts; mod dither; -- cgit v1.2.3