From bf8e0500eb1e6932501266716f1a5e8b66f802fc Mon Sep 17 00:00:00 2001 From: elwrcl Date: Fri, 2 Oct 2026 18:29:46 +0300 Subject: [PATCH] fix: show finished shapes as the export draws them --- src/editor/doc.rs | 27 +++++++++++++++++++++++++++ src/editor/mod.rs | 20 +++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/editor/doc.rs b/src/editor/doc.rs index be318b3..7684c86 100644 --- a/src/editor/doc.rs +++ b/src/editor/doc.rs @@ -8,6 +8,7 @@ pub struct Doc { shapes: Vec, redo: Vec, saved: Vec, + revision: u64, } impl Doc { @@ -22,6 +23,7 @@ impl Doc { pub fn add(&mut self, shape: Shape) { self.shapes.push(shape); self.redo.clear(); + self.revision += 1; } pub fn undo(&mut self) -> bool { @@ -29,6 +31,7 @@ impl Doc { return false; }; self.redo.push(shape); + self.revision += 1; true } @@ -37,9 +40,15 @@ impl Doc { return false; }; self.shapes.push(shape); + self.revision += 1; true } + /// Changes whenever the drawn shapes do. + pub fn revision(&self) -> u64 { + self.revision + } + pub fn can_undo(&self) -> bool { !self.shapes.is_empty() } @@ -87,6 +96,24 @@ mod tests { assert!(!d.redo()); } + #[test] + fn revision_follows_the_shapes() { + let mut d = Doc::new(); + let r0 = d.revision(); + d.add(line(1.0)); + let r1 = d.revision(); + assert_ne!(r1, r0); + d.mark_saved(); + assert_eq!(d.revision(), r1, "saving doesn't change what is drawn"); + d.undo(); + assert_ne!(d.revision(), r1); + let r2 = d.revision(); + assert!(!d.undo(), "nothing left"); + assert_eq!(d.revision(), r2); + d.redo(); + assert_ne!(d.revision(), r2); + } + #[test] fn a_new_shape_clears_redo() { let mut d = Doc::new(); diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 69485ec..87a77c1 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -52,7 +52,11 @@ pub fn run(path: &Path) -> Result<()> { struct Editor { path: PathBuf, base: RgbaImage, + /// The base with every finished shape, drawn by the export renderer so + /// the canvas shows the saved pixels. texture: egui::TextureHandle, + /// The `Doc::revision` the texture shows. + shown: u64, doc: Doc, tool: Tool, color: usize, @@ -74,6 +78,7 @@ impl Editor { path, base, texture, + shown: 0, doc: Doc::new(), tool: Tool::Arrow, color: 0, @@ -299,6 +304,14 @@ impl Editor { Color32::WHITE, ); + if self.doc.revision() != self.shown { + let composite = export::render(&self.base, self.doc.shapes()); + let size = [composite.width() as usize, composite.height() as usize]; + let pixels = egui::ColorImage::from_rgba_unmultiplied(size, composite.as_raw()); + self.texture.set(pixels, egui::TextureOptions::LINEAR); + self.shown = self.doc.revision(); + } + let shift = ui.input(|i| i.modifiers.shift); let pointer = response .interact_pointer_pos() @@ -321,9 +334,10 @@ impl Editor { } } - let live = self.drag.as_ref().map(|d| d.shape(shift)); - for shape in self.doc.shapes().iter().chain(live.as_ref()) { - for prim in geometry(shape) { + // Finished shapes are in the texture; only the one being drawn is + // painted here. + if let Some(live) = self.drag.as_ref().map(|d| d.shape(shift)) { + for prim in geometry(&live) { paint(&painter, &prim, fit.scale, to_pos); } }