From 65995213058f2b92f5c7abd62e5bcb76fbf1d3ed Mon Sep 17 00:00:00 2001 From: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Date: Tue, 13 Oct 2026 18:43:26 +0200 Subject: [PATCH] fix: drop the background render when a display option changes (#730) --- crates/ui-egui/src/canvas.rs | 63 ++++++++++++++++++++++++++++++++++++ crates/ui-egui/src/lib.rs | 3 ++ 2 files changed, 66 insertions(+) diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 077ae294..a681fca9 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -365,10 +365,57 @@ fn cursor_icon(c: Cursor) -> egui::CursorIcon { } } +/// The display options that change how the canvas texture looks without touching the document. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct DisplayKey { + quality: designcraft_render::DisplayQuality, + separation: Option, + rich_black: bool, + overprint_preview: bool, + proof_colors: bool, + tag_markers: bool, + highlight_substituted_fonts: bool, + highlight_hj: bool, + show_note_anchors: bool, + show_added_text: bool, + highlight_keeps: bool, + highlight_custom_tracking: bool, +} + +fn display_key(app: &DesignApp) -> DisplayKey { + let (ui, prefs) = (&app.ui, &app.session.prefs); + DisplayKey { + quality: ui.display_quality, + separation: ui.separation, + rich_black: ui.rich_black, + overprint_preview: ui.overprint_preview, + proof_colors: ui.proof_colors, + tag_markers: ui.tag_markers, + highlight_substituted_fonts: prefs.highlight_substituted_fonts, + highlight_hj: prefs.highlight_hj, + show_note_anchors: prefs.show_note_anchors, + show_added_text: prefs.show_added_text, + highlight_keeps: prefs.highlight_keeps, + highlight_custom_tracking: prefs.highlight_custom_tracking, + } +} + +/// When a display option changed, drop the texture and any render in flight: they were drawn with the old options. +fn invalidate_on_display_change(app: &mut DesignApp) { + let key = display_key(app); + if app.canvas.display_key != Some(key) { + app.canvas.display_key = Some(key); + app.canvas.shown = None; + app.canvas.pending = None; + app.canvas.pending_doc = None; + } +} + /// Keep the canvas texture current. Panning inside the overscanned region just shifts the /// texture; zooming shows the old texture scaled until the background render arrives; document /// edits render synchronously so editing never lags. fn render_texture(app: &mut DesignApp, ctx: &egui::Context, rect: Rect, xf: &Xf, layout: &CanvasLayout, preview: bool) { + invalidate_on_display_change(app); let Some(st) = app.session.active() else { return }; let ppp = ctx.pixels_per_point() as f64; let doc_key = (st.uid, std::sync::Arc::as_ptr(&st.doc) as u64, st.revision, preview); @@ -1791,6 +1838,22 @@ mod tests { h } + #[test] + fn display_option_change_drops_the_render_in_flight() { + let mut app = DesignApp::new(designcraft_engine::Session::new(), crate::Services::default()); + let shown = crate::Shown { doc: (1, 2, 3, false), origin: Point::new(0.0, 0.0), zoom: 1.0, size: (10.0, 10.0) }; + invalidate_on_display_change(&mut app); + app.canvas.shown = Some(shown); + app.canvas.pending = Some((7, shown)); + // Nothing changed: the texture and the request stay. + invalidate_on_display_change(&mut app); + assert!(app.canvas.shown.is_some() && app.canvas.pending.is_some()); + // A display option changed while the render ran: its result must not be accepted. + app.ui.display_quality = designcraft_render::DisplayQuality::Fast; + invalidate_on_display_change(&mut app); + assert!(app.canvas.shown.is_none() && app.canvas.pending.is_none() && app.canvas.pending_doc.is_none()); + } + fn right_click(h: &mut Harness<'_, DesignApp>, p: Pos2) { h.hover_at(p); h.step(); diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index fc7a3e63..08dfd2d4 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -432,6 +432,7 @@ impl CanvasCache { last_ms: 0.0, shown_doc: None, pending_doc: None, + display_key: None, patcher: designcraft_render::Renderer::new(), patches: 0, } @@ -459,6 +460,8 @@ pub struct CanvasCache { pub shown_doc: Option>, /// Document of the request in flight. pub pending_doc: Option>, + /// Display options the texture and the request in flight were rendered with. + pub display_key: Option, /// Renders damaged regions (its own context: region sizes vary). pub patcher: designcraft_render::Renderer, /// Partial repaints / full renders since start (perf readout).