From 63a9a11e7f332d481a83a8637cf27b1614ec79f3 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:27:18 +0200 Subject: [PATCH 1/5] add a note on rendernode retention when trashing strokes --- crates/rnote-engine/src/store/trash_comp.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/rnote-engine/src/store/trash_comp.rs b/crates/rnote-engine/src/store/trash_comp.rs index cf7e1bb4ba..9976c5d162 100644 --- a/crates/rnote-engine/src/store/trash_comp.rs +++ b/crates/rnote-engine/src/store/trash_comp.rs @@ -51,6 +51,8 @@ impl StrokeStore { trash_comp.trashed = trash; // remove the key from the rtree (so that the rtree holds information // only for non trashed strokes) + // Remark : the corresponding stroke will hold onto its rendernodes and image + // until `regenerate_rendering_in_viewport_threaded` is called again if trash { self.key_tree.remove_with_key(key); } else { From a0bc4622012a75049fe69ce1cb648d3aec9bc463 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:48:29 +0200 Subject: [PATCH 2/5] clean up interfaces Do not leak key trees out of the store structure --- crates/rnote-engine/src/document/mod.rs | 4 ++-- crates/rnote-engine/src/store/keytree.rs | 4 ++-- crates/rnote-engine/src/store/mod.rs | 7 ++++++- crates/rnote-engine/src/store/render_comp.rs | 2 +- crates/rnote-engine/src/store/stroke_comp.rs | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/rnote-engine/src/document/mod.rs b/crates/rnote-engine/src/document/mod.rs index 929b38c5e5..9253d32cff 100644 --- a/crates/rnote-engine/src/document/mod.rs +++ b/crates/rnote-engine/src/document/mod.rs @@ -257,7 +257,7 @@ impl Document { ); if include_content { - let rendered_bounds = store.key_tree.get_bounds(); + let rendered_bounds = store.get_bounds(); let content_bounds = if rendered_bounds.area() > 0.0 { Aabb::new( @@ -306,7 +306,7 @@ impl Document { .merged(&viewport.extend_by(na::vector![padding_horizontal, padding_vertical])); if include_content { - let rendered_bounds = store.key_tree.get_bounds(); + let rendered_bounds = store.get_bounds(); let content_bounds = if rendered_bounds.area() > 0.0 { Aabb::new( diff --git a/crates/rnote-engine/src/store/keytree.rs b/crates/rnote-engine/src/store/keytree.rs index 9df2f60bfd..e27a39a28e 100644 --- a/crates/rnote-engine/src/store/keytree.rs +++ b/crates/rnote-engine/src/store/keytree.rs @@ -5,13 +5,13 @@ use rstar::AABB; use rstar::primitives::GeomWithData; /// The rtree object that holds the bounds and [StrokeKey]. -pub(crate) type KeyTreeObject = GeomWithData, StrokeKey>; +type KeyTreeObject = GeomWithData, StrokeKey>; #[derive(Debug, Default)] /// A Rtree with [StrokeKey]'s as associated data. /// /// Used for faster spatial queries. -pub(crate) struct KeyTree(rstar::RTree); +pub(super) struct KeyTree(rstar::RTree); impl KeyTree { /// Insert a new tree object with the given [StrokeKey] and bounds. diff --git a/crates/rnote-engine/src/store/mod.rs b/crates/rnote-engine/src/store/mod.rs index 73ca637ad7..532983d5c6 100644 --- a/crates/rnote-engine/src/store/mod.rs +++ b/crates/rnote-engine/src/store/mod.rs @@ -10,6 +10,7 @@ pub mod trash_comp; pub use chrono_comp::ChronoComponent; use keytree::KeyTree; pub use render_comp::RenderComponent; +use rstar::AABB; pub use selection_comp::SelectionComponent; pub use trash_comp::TrashComponent; @@ -95,7 +96,7 @@ pub struct StrokeStore { /// /// Needs to be updated with `update_with_key()` when strokes changed their geometry or position! #[serde(skip)] - pub(crate) key_tree: KeyTree, + key_tree: KeyTree, } impl Default for StrokeStore { @@ -383,4 +384,8 @@ impl StrokeStore { widget_flags } + + pub(super) fn get_bounds(&self) -> AABB<[f64; 2]> { + self.key_tree.get_bounds() + } } diff --git a/crates/rnote-engine/src/store/render_comp.rs b/crates/rnote-engine/src/store/render_comp.rs index e2c71ca0ef..484b9e4806 100644 --- a/crates/rnote-engine/src/store/render_comp.rs +++ b/crates/rnote-engine/src/store/render_comp.rs @@ -700,7 +700,7 @@ impl StrokeStore { } // draw the rtree root - let tree_bounds = self.key_tree.get_tree().root().envelope(); + let tree_bounds = self.key_tree.get_bounds(); visual_debug::draw_bounds_to_gtk_snapshot( Aabb::new( na::point![tree_bounds.lower()[0], tree_bounds.lower()[1]], diff --git a/crates/rnote-engine/src/store/stroke_comp.rs b/crates/rnote-engine/src/store/stroke_comp.rs index e638c54ca6..7d53dc9b6e 100644 --- a/crates/rnote-engine/src/store/stroke_comp.rs +++ b/crates/rnote-engine/src/store/stroke_comp.rs @@ -140,7 +140,7 @@ impl StrokeStore { /// Calculate the height needed to fit all strokes. pub(crate) fn calc_height(&self) -> f64 { - let bounds = self.key_tree.get_tree().root().envelope(); + let bounds = self.key_tree.get_bounds(); bounds.upper()[1] - bounds.lower()[1] } From 769fe09cf34fc1ce966d57939c9171cfb234c39e Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:51:30 +0200 Subject: [PATCH 3/5] rappatriate window ci fixes --- build-aux/inno_build.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build-aux/inno_build.py b/build-aux/inno_build.py index 50356ea452..86686dc275 100644 --- a/build-aux/inno_build.py +++ b/build-aux/inno_build.py @@ -70,6 +70,16 @@ def run_command(command, error_message): f"Collecting angle dependency ({angle_dll}) DLLs failed", ) +# add libcrypto-3-x64.dll and libssl-3-x64.dll +run_command( + f"cp {build_environment_path}/bin/libcrypto-3-x64.dll {dlls_dir}", + "Collecting libcrypto-3-x64.dll failed", +) +run_command( + f"cp {build_environment_path}/bin/libssl-3-x64.dll {dlls_dir}", + "Collecting libssl-3-x64.dll failed", +) + # Collect necessary GSchema Xml's and compile them into a `gschemas.compiled` print("Collecting and compiling GSchemas...", file=sys.stderr) gschemas_dir = os.path.join(build_root, "gschemas") From 4b5577f890a14917a4c780d9b773f0e72e5bffa4 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 7 Jun 2025 12:08:36 +0200 Subject: [PATCH 4/5] fix typo --- crates/rnote-engine/src/store/render_comp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rnote-engine/src/store/render_comp.rs b/crates/rnote-engine/src/store/render_comp.rs index 484b9e4806..067e930421 100644 --- a/crates/rnote-engine/src/store/render_comp.rs +++ b/crates/rnote-engine/src/store/render_comp.rs @@ -339,7 +339,7 @@ impl StrokeStore { // iterate a second time on stroke keys that we know are not in // the viewport - // This way we can skip calculting their bounds + // This way we can skip calculating their bounds for (_key, render_comp) in self .render_components .iter_mut() From b7505ed13be612316dfea1f69684b86b35b749b9 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 7 Jun 2025 12:24:33 +0200 Subject: [PATCH 5/5] handle correctly empty keytree for `resize_doc` methods --- crates/rnote-engine/src/document/mod.rs | 12 ++++++------ crates/rnote-engine/src/store/keytree.rs | 4 ++++ crates/rnote-engine/src/store/mod.rs | 4 ++++ crates/rnote-engine/src/store/stroke_comp.rs | 8 ++++++-- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/crates/rnote-engine/src/document/mod.rs b/crates/rnote-engine/src/document/mod.rs index 9253d32cff..caf14ccc31 100644 --- a/crates/rnote-engine/src/document/mod.rs +++ b/crates/rnote-engine/src/document/mod.rs @@ -257,18 +257,18 @@ impl Document { ); if include_content { - let rendered_bounds = store.get_bounds(); + let content_bounds = if store.keytree_is_empty() { + // If doc is empty, resize to one page with the format size + Aabb::new(na::point![0.0, 0.0], self.config.format.size().into()) + .extend_right_and_bottom_by(na::vector![padding_horizontal, padding_vertical]) + } else { + let rendered_bounds = store.get_bounds(); - let content_bounds = if rendered_bounds.area() > 0.0 { Aabb::new( na::point![rendered_bounds.lower()[0], rendered_bounds.lower()[1]], na::point![rendered_bounds.upper()[0], rendered_bounds.upper()[1]], ) .extend_right_and_bottom_by(na::vector![padding_horizontal, padding_vertical]) - } else { - // If doc is empty, resize to one page with the format size - Aabb::new(na::point![0.0, 0.0], self.config.format.size().into()) - .extend_right_and_bottom_by(na::vector![padding_horizontal, padding_vertical]) }; new_bounds.merge(&content_bounds); } diff --git a/crates/rnote-engine/src/store/keytree.rs b/crates/rnote-engine/src/store/keytree.rs index e27a39a28e..97fef6bd06 100644 --- a/crates/rnote-engine/src/store/keytree.rs +++ b/crates/rnote-engine/src/store/keytree.rs @@ -78,6 +78,10 @@ impl KeyTree { pub fn get_bounds(&self) -> AABB<[f64; 2]> { self.0.root().envelope() } + + pub(crate) fn is_empty(&self) -> bool { + self.0.size() == 0 + } } fn new_keytree_object(key: StrokeKey, bounds: Aabb) -> KeyTreeObject { diff --git a/crates/rnote-engine/src/store/mod.rs b/crates/rnote-engine/src/store/mod.rs index 532983d5c6..4d9f35d22f 100644 --- a/crates/rnote-engine/src/store/mod.rs +++ b/crates/rnote-engine/src/store/mod.rs @@ -388,4 +388,8 @@ impl StrokeStore { pub(super) fn get_bounds(&self) -> AABB<[f64; 2]> { self.key_tree.get_bounds() } + + pub(super) fn keytree_is_empty(&self) -> bool { + self.key_tree.is_empty() + } } diff --git a/crates/rnote-engine/src/store/stroke_comp.rs b/crates/rnote-engine/src/store/stroke_comp.rs index 7d53dc9b6e..cf0bf0ef55 100644 --- a/crates/rnote-engine/src/store/stroke_comp.rs +++ b/crates/rnote-engine/src/store/stroke_comp.rs @@ -140,8 +140,12 @@ impl StrokeStore { /// Calculate the height needed to fit all strokes. pub(crate) fn calc_height(&self) -> f64 { - let bounds = self.key_tree.get_bounds(); - bounds.upper()[1] - bounds.lower()[1] + if self.keytree_is_empty() { + return 0.0; + } else { + let bounds = self.key_tree.get_bounds(); + bounds.upper()[1] - bounds.lower()[1] + } } /// Calculate the width needed to fit all strokes.