From b803598b7983101ae5d1056331329056dc04abfc Mon Sep 17 00:00:00 2001 From: Felix Zwettler Date: Fri, 6 May 2022 23:33:08 +0200 Subject: [PATCH] fix layout manager state --- rnote-ui/src/canvas/canvaslayout.rs | 63 ++++++++++++++++------------- rnote-ui/src/canvas/mod.rs | 7 ++++ 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/rnote-ui/src/canvas/canvaslayout.rs b/rnote-ui/src/canvas/canvaslayout.rs index 443ad630e0..79a9736255 100644 --- a/rnote-ui/src/canvas/canvaslayout.rs +++ b/rnote-ui/src/canvas/canvaslayout.rs @@ -1,20 +1,22 @@ -mod imp { - use std::cell::Cell; - use std::rc::Rc; +use std::cell::Cell; +use std::rc::Rc; + +use gtk4::{ + glib, prelude::*, subclass::prelude::*, LayoutManager, Orientation, SizeRequestMode, Widget, +}; +use p2d::bounding_volume::{BoundingVolume, AABB}; +use rnote_compose::helpers::AABBHelpers; - use gtk4::{ - glib, prelude::*, subclass::prelude::*, LayoutManager, Orientation, SizeRequestMode, Widget, - }; - use p2d::bounding_volume::{BoundingVolume, AABB}; - use rnote_compose::helpers::AABBHelpers; +use crate::canvas::RnoteCanvas; +use rnote_engine::sheet::ExpandMode; +use rnote_engine::{render, Sheet}; - use crate::canvas::RnoteCanvas; - use rnote_engine::sheet::ExpandMode; - use rnote_engine::{render, Sheet}; +mod imp { + use super::*; #[derive(Debug, Clone)] pub struct CanvasLayout { - old_viewport: Rc>, + pub old_viewport: Rc>, } impl Default for CanvasLayout { @@ -141,29 +143,27 @@ mod imp { .update_background_rendering_current_viewport(); let viewport = canvas.engine().borrow().camera.viewport(); - let viewport_extents = viewport.extents(); let old_viewport = self.old_viewport.get(); - let old_viewport_extents = old_viewport.extents(); - - let old_viewport_render_margins = - old_viewport.extents() * render::VIEWPORT_EXTENTS_MARGIN_FACTOR; + // We only extend the viewport by half of the margin, because we want to trigger rendering before we reach it. + // This has two advantages: Strokes that might take longer to render have a head start while still being out of view, + // And the rendering gets triggered more often, so not that many strokes start to get rendered. This avoids stutters, + // because while the rendering itself is on worker threads, we still have to `integrate` the resulted textures, + // which can also take up quite some time on the main UI thread. + let old_viewport_extended = old_viewport + .extend_by(old_viewport.extents() * render::VIEWPORT_EXTENTS_MARGIN_FACTOR * 0.5); /* log::debug!( - "viewport: {:#?}\nold_loosened_viewport: {:#?}", + "viewport: {:#?}\nold_viewport_extended: {:#?}", viewport, - old_loosened_viewport + old_viewport_extended ); */ - // Either when we have zoomed out beyond the extended old viewport - if viewport_extents > old_viewport_extents * render::VIEWPORT_EXTENTS_MARGIN_FACTOR - // or if the viewport is moved beyond the extended old viewport - || !old_viewport - .extend_by(old_viewport_render_margins) - .contains(&viewport) - { - // conditionally update the engine rendering when the thresholds are crossed + // On zoom outs or viewport translations this will evaluate true, so we render the strokes that are coming into view. + // But after zoom ins we need to update old_viewport with layout_manager.update_state() + if !old_viewport_extended.contains(&viewport) { + // Because we don't set the rendering of strokes that are already in the view dirty, we only render those that may come into the view. canvas .engine() .borrow_mut() @@ -175,8 +175,6 @@ mod imp { } } -use gtk4::{glib, LayoutManager}; - glib::wrapper! { pub struct CanvasLayout(ObjectSubclass) @extends LayoutManager; @@ -192,4 +190,11 @@ impl CanvasLayout { pub fn new() -> Self { glib::Object::new(&[]).expect("Failed to create CanvasLayout") } + + // needs to be called after zooming + pub fn update_state(&self, canvas: &RnoteCanvas) { + self.imp() + .old_viewport + .set(canvas.engine().borrow().camera.viewport()); + } } diff --git a/rnote-ui/src/canvas/mod.rs b/rnote-ui/src/canvas/mod.rs index 10eccfe722..b38429a432 100644 --- a/rnote-ui/src/canvas/mod.rs +++ b/rnote-ui/src/canvas/mod.rs @@ -799,6 +799,13 @@ impl RnoteCanvas { self.regenerate_background_pattern(); self.update_engine_rendering(); + + // We need to update the layout managers internal state after zooming + self.layout_manager() + .unwrap() + .downcast::() + .unwrap() + .update_state(self); } /// Zooms temporarily and then scale the canvas and its contents to a new zoom after a given time.