fix: show finished shapes as the export draws them

This commit is contained in:
elwrcl committed 2026-10-02 18:31:29 +03:00
1 parent cf8b043e1f
commit bf8e0500eb
2 files changed
+44 -3

No files matched your search

+27
View File
@@ -8,6 +8,7 @@ pub struct Doc {
shapes: Vec<Shape>, shapes: Vec<Shape>,
redo: Vec<Shape>, redo: Vec<Shape>,
saved: Vec<Shape>, saved: Vec<Shape>,
revision: u64,
} }
impl Doc { impl Doc {
@@ -22,6 +23,7 @@ impl Doc {
pub fn add(&mut self, shape: Shape) { pub fn add(&mut self, shape: Shape) {
self.shapes.push(shape); self.shapes.push(shape);
self.redo.clear(); self.redo.clear();
self.revision += 1;
} }
pub fn undo(&mut self) -> bool { pub fn undo(&mut self) -> bool {
@@ -29,6 +31,7 @@ impl Doc {
return false; return false;
}; };
self.redo.push(shape); self.redo.push(shape);
self.revision += 1;
true true
} }
@@ -37,9 +40,15 @@ impl Doc {
return false; return false;
}; };
self.shapes.push(shape); self.shapes.push(shape);
self.revision += 1;
true true
} }
/// Changes whenever the drawn shapes do.
pub fn revision(&self) -> u64 {
self.revision
}
pub fn can_undo(&self) -> bool { pub fn can_undo(&self) -> bool {
!self.shapes.is_empty() !self.shapes.is_empty()
} }
@@ -87,6 +96,24 @@ mod tests {
assert!(!d.redo()); 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] #[test]
fn a_new_shape_clears_redo() { fn a_new_shape_clears_redo() {
let mut d = Doc::new(); let mut d = Doc::new();
+17 -3
View File
@@ -52,7 +52,11 @@ pub fn run(path: &Path) -> Result<()> {
struct Editor { struct Editor {
path: PathBuf, path: PathBuf,
base: RgbaImage, base: RgbaImage,
/// The base with every finished shape, drawn by the export renderer so
/// the canvas shows the saved pixels.
texture: egui::TextureHandle, texture: egui::TextureHandle,
/// The `Doc::revision` the texture shows.
shown: u64,
doc: Doc, doc: Doc,
tool: Tool, tool: Tool,
color: usize, color: usize,
@@ -74,6 +78,7 @@ impl Editor {
path, path,
base, base,
texture, texture,
shown: 0,
doc: Doc::new(), doc: Doc::new(),
tool: Tool::Arrow, tool: Tool::Arrow,
color: 0, color: 0,
@@ -299,6 +304,14 @@ impl Editor {
Color32::WHITE, 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 shift = ui.input(|i| i.modifiers.shift);
let pointer = response let pointer = response
.interact_pointer_pos() .interact_pointer_pos()
@@ -321,9 +334,10 @@ impl Editor {
} }
} }
let live = self.drag.as_ref().map(|d| d.shape(shift)); // Finished shapes are in the texture; only the one being drawn is
for shape in self.doc.shapes().iter().chain(live.as_ref()) { // painted here.
for prim in geometry(shape) { 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); paint(&painter, &prim, fit.scale, to_pos);
} }
} }