line.rs - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
 (HTM) git clone https://git.drkhsh.at/icy_draw.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       line.rs (4660B)
       ---
            1 #![allow(clippy::comparison_chain)]
            2 use icy_engine::Position;
            3 use icy_engine_egui::BufferView;
            4 
            5 use super::{plot_point, BrushMode, ColorMode, PointRole};
            6 
            7 fn get_line_points(from: Position, to: Position) -> Vec<Position> {
            8     let dx = (to.x - from.x).abs();
            9     let sx = if from.x < to.x { 1 } else { -1 };
           10     let dy = (to.y - from.y).abs();
           11     let sy = if from.y < to.y { 1 } else { -1 };
           12 
           13     let mut err = if dx > dy { dx } else { -dy } / 2;
           14 
           15     let mut result = Vec::new();
           16     let mut cur = from;
           17     loop {
           18         result.push(cur);
           19         if cur == to {
           20             break;
           21         }
           22 
           23         let e2 = err;
           24         if e2 > -dx {
           25             err -= dy;
           26             cur.x += sx;
           27         }
           28         if e2 < dy {
           29             err += dx;
           30             cur.y += sy;
           31         }
           32     }
           33     result
           34 }
           35 
           36 pub fn draw_line(buffer_view: &mut BufferView, from: impl Into<Position>, to: impl Into<Position>, mode: BrushMode, color_mode: ColorMode) {
           37     let mut from = from.into();
           38     let mut to = to.into();
           39     let mut y_mul = 1;
           40     if !matches!(mode, BrushMode::HalfBlock) {
           41         from.y /= 2;
           42         to.y /= 2;
           43         y_mul = 2;
           44     }
           45 
           46     let mut v = get_line_points(from, to);
           47     if v.is_empty() {
           48         return;
           49     }
           50     if !matches!(mode, BrushMode::Outline) {
           51         for point in get_line_points(from, to) {
           52             plot_point(buffer_view, (point.x, point.y * y_mul), mode.clone(), color_mode, PointRole::Line);
           53         }
           54         return;
           55     }
           56     let mut n = Vec::new();
           57     for pt in v {
           58         let p = Position::new(pt.x, 2 * (pt.y / 2));
           59         if let Some(l) = n.last() {
           60             if p == *l {
           61                 continue;
           62             }
           63         }
           64         n.push(p);
           65     }
           66     v = n;
           67     let mut last = v[0];
           68     let mut i = 0;
           69     while i < v.len() {
           70         let is_last = i + 1 >= v.len();
           71         let next = if is_last {
           72             Position::new(v[i].x + v[i].x - last.x, v[i].y + v[i].y + last.y)
           73         } else {
           74             v[i + 1]
           75         };
           76         let point = v[i];
           77         last = point;
           78         let cy2 = point.y;
           79         let ny2 = next.y;
           80 
           81         let role = if point.x > next.x {
           82             // Left side
           83             if ny2 < cy2 {
           84                 println!("plot ne corner above");
           85                 plot_point(buffer_view, point + Position::new(0, -1), mode.clone(), color_mode, PointRole::NECorner);
           86                 PointRole::SWCorner
           87             } else if ny2 > cy2 {
           88                 println!("plot se corner below");
           89                 plot_point(buffer_view, point + Position::new(0, 2), mode.clone(), color_mode, PointRole::SECorner);
           90                 PointRole::NWCorner
           91             } else {
           92                 PointRole::TopSide
           93             }
           94         } else if point.x < next.x {
           95             // Right Side
           96             if ny2 < cy2 {
           97                 println!("plot nw corner above");
           98                 plot_point(buffer_view, point + Position::new(0, -1), mode.clone(), color_mode, PointRole::NWCorner);
           99                 PointRole::SECorner
          100             } else if ny2 > cy2 {
          101                 println!("plot sw corner below");
          102                 plot_point(buffer_view, point + Position::new(0, 2), mode.clone(), color_mode, PointRole::SWCorner);
          103                 PointRole::NECorner
          104             } else {
          105                 // telel
          106                 if point.x < next.x {
          107                     if point.y == next.y {
          108                         println!("top side right 1");
          109                         PointRole::TopSide
          110                     } else {
          111                         println!("plot ne corner right");
          112                         i += 1;
          113                         plot_point(buffer_view, point + Position::new(1, 0), mode.clone(), color_mode, PointRole::NECorner);
          114                         PointRole::SWCorner
          115                     }
          116                 } else if point.x > next.x {
          117                     println!("plot nw corner left");
          118                     plot_point(buffer_view, point + Position::new(-1, 0), mode.clone(), color_mode, PointRole::NWCorner);
          119                     PointRole::SECorner
          120                 } else {
          121                     // case 4
          122                     if last.y == point.y {
          123                         println!("top side right 2");
          124                         PointRole::TopSide
          125                     } else {
          126                         println!("plot ne corner right");
          127                         plot_point(buffer_view, point + Position::new(1, 0), mode.clone(), color_mode, PointRole::NECorner);
          128                         PointRole::SWCorner
          129                     }
          130                 }
          131             }
          132         } else {
          133             PointRole::LeftSide
          134         };
          135         plot_point(buffer_view, point, mode.clone(), color_mode, role);
          136         i += 1;
          137     }
          138 }