Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/release-windows.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
---

name: Release Windows

"on":
Expand All @@ -9,14 +8,24 @@ name: Release Windows

jobs:
build:
runs-on: windows-2022
runs-on: windows-2025
permissions:
# needed for uploading release artifact
contents: write
defaults:
run:
shell: msys2 {0}
steps:
- name: Install Inno 6
id: install_inno
shell: pwsh
run: |
winget install -e --id JRSoftware.InnoSetup -v 6.4.3 --accept-package-agreements --accept-source-agreements --disable-interactivity --scope machine
if (Test-Path "C:\Program Files (x86)\Inno Setup 6\") {
echo "inno installed successfully"
} else {
throw "could not find inno's installation folder"
}

- name: Set installer name
id: set_installer_name
Expand Down
21 changes: 21 additions & 0 deletions crates/rnote-compose/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ where
/// splits a aabb into multiple which have a maximum of the given size. Their union is the given aabb.
/// the split bounds are exactly fitted to not overlap, or extend the given bounds
fn split(self, split_size: na::Vector2<f64>) -> Vec<Self>;
/// get the top patch for a given split size
fn get_origin(self, split_size: na::Vector2<f64>, split_order: SplitOrder) -> Self;
/// splits a aabb into multiple of the given size. Their union contains the given aabb.
/// The boxes on the edges most likely extend beyond the given aabb.
fn split_extended(self, split_size: na::Vector2<f64>) -> Vec<Self>;
Expand Down Expand Up @@ -394,6 +396,25 @@ impl AabbExt for Aabb {
split_aabbs
}

fn get_origin(self, split_size: na::Vector2<f64>, split_order: SplitOrder) -> Self {
let (outer_idx, inner_idx) = match split_order {
SplitOrder::RowMajor => (1, 0),
SplitOrder::ColumnMajor => (0, 1),
};

let offset_outer =
(self.mins[outer_idx] / split_size[outer_idx]).floor() * split_size[outer_idx];

let offset_inner =
(self.mins[inner_idx] / split_size[inner_idx]).floor() * split_size[inner_idx];

let mins = match split_order {
SplitOrder::RowMajor => na::point![offset_inner, offset_outer],
SplitOrder::ColumnMajor => na::point![offset_outer, offset_inner],
};
Aabb::new(mins, mins + split_size)
}

fn split_extended_origin_aligned(
self,
split_size: na::Vector2<f64>,
Expand Down
24 changes: 17 additions & 7 deletions crates/rnote-engine/src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub use background::Background;
pub use config::DocumentConfig;
pub use format::Format;
pub use layout::Layout;
use rstar::Envelope;

// Imports
use crate::engine::EngineConfig;
Expand Down Expand Up @@ -256,10 +257,14 @@ impl Document {
);

if include_content {
let keys = store.stroke_keys_as_rendered();
let content_bounds = if let Some(content_bounds) = store.bounds_for_strokes(&keys) {
content_bounds
.extend_right_and_bottom_by(na::vector![padding_horizontal, padding_vertical])
let rendered_bounds = store.key_tree.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())
Expand Down Expand Up @@ -301,9 +306,14 @@ impl Document {
.merged(&viewport.extend_by(na::vector![padding_horizontal, padding_vertical]));

if include_content {
let keys = store.stroke_keys_as_rendered();
let content_bounds = if let Some(content_bounds) = store.bounds_for_strokes(&keys) {
content_bounds.extend_by(na::vector![padding_horizontal, padding_vertical])
let rendered_bounds = store.key_tree.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())
Expand Down
6 changes: 4 additions & 2 deletions crates/rnote-engine/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ pub struct Engine {
background_tile_image: Option<render::Image>,
#[cfg(feature = "ui")]
#[serde(skip)]
background_rendernodes: Vec<gtk4::gsk::RenderNode>,
background_rendernode: Option<gtk4::gsk::RenderNode>,
origin_background_rendernode: Option<Aabb>,
// Origin indicator rendering
#[serde(skip)]
origin_indicator_image: Option<render::Image>,
Expand All @@ -225,7 +226,8 @@ impl Default for Engine {
tasks_rx: Some(EngineTaskReceiver(tasks_rx)),
background_tile_image: None,
#[cfg(feature = "ui")]
background_rendernodes: Vec::default(),
background_rendernode: None,
origin_background_rendernode: None,
origin_indicator_image: None,
#[cfg(feature = "ui")]
origin_indicator_rendernode: None,
Expand Down
94 changes: 71 additions & 23 deletions crates/rnote-engine/src/engine/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ impl Engine {
use rnote_compose::ext::AabbExt;

let viewport = self.camera.viewport();
let mut rendernodes: Vec<gsk::RenderNode> = vec![];

if let Some(image) = &self.background_tile_image {
// Only create the texture once, it is expensive
Expand All @@ -35,21 +34,20 @@ impl Engine {
}
};

for split_bounds in viewport.split_extended_origin_aligned(
let origin_aabb = viewport.get_origin(
self.document.config.background.tile_size(),
SplitOrder::default(),
) {
rendernodes.push(
gsk::TextureNode::new(
&new_texture,
&graphene::Rect::from_p2d_aabb(split_bounds),
)
.upcast(),
);
}
}
);

self.background_rendernodes = rendernodes;
self.background_rendernode = Some(
gsk::TextureNode::new(
&new_texture,
&graphene::Rect::from_p2d_aabb(origin_aabb),
)
.upcast(),
);
self.origin_background_rendernode = Some(origin_aabb);
}
}

#[cfg(feature = "ui")]
Expand Down Expand Up @@ -117,7 +115,8 @@ impl Engine {
self.origin_indicator_image.take();
#[cfg(feature = "ui")]
{
self.background_rendernodes.clear();
self.background_rendernode = None;
self.origin_background_rendernode = None;
self.origin_indicator_rendernode.take();
}
widget_flags.redraw = true;
Expand Down Expand Up @@ -163,23 +162,45 @@ impl Engine {
snapshot: &gtk4::Snapshot,
surface_bounds: p2d::bounding_volume::Aabb,
) -> anyhow::Result<()> {
use std::time::SystemTime;

use crate::drawable::DrawableOnDoc;
use crate::engine::visual_debug;
use crate::engine_view;
use gtk4::prelude::*;

let start_rendering = SystemTime::now();

let doc_bounds = self.document.bounds();
let viewport = self.camera.viewport();
let camera_transform = self.camera.transform_for_gtk_snapshot();

snapshot.save();
snapshot.transform(Some(&camera_transform));
self.draw_document_shadow_to_gtk_snapshot(snapshot);
self.draw_background_to_gtk_snapshot(snapshot)?;
self.draw_format_borders_to_gtk_snapshot(snapshot)?;
self.draw_origin_indicator_to_gtk_snapshot(snapshot)?;

let elapsed_snapshot_setup = start_rendering.elapsed();

// expensive but constant time : can we not translate ?
// seems like the gtk snapshot does NOT maintain layer so we'd need
// to hold stacked widgets for this
// OR hold onto render nodes and translates then instead
let draw_doc_shadow_start = SystemTime::now();
self.draw_document_shadow_to_gtk_snapshot(snapshot); // constant time (or should be)
let draw_doc_shadow_elapsed = draw_doc_shadow_start.elapsed();
let draw_bgrd_start = SystemTime::now();
self.draw_background_to_gtk_snapshot(snapshot)?; // constant time (or should be)
let draw_bgrd_elapsed = draw_bgrd_start.elapsed();
let draw_fmt_start = SystemTime::now();
self.draw_format_borders_to_gtk_snapshot(snapshot)?; // constant time (or should be)
let draw_fmt_elapsed = draw_fmt_start.elapsed();
let draw_orig_start = SystemTime::now();
self.draw_origin_indicator_to_gtk_snapshot(snapshot)?; // constant time (or should be)
let draw_orig_elapsed = draw_orig_start.elapsed();
let draw_stroke_start = SystemTime::now();
self.store
.draw_strokes_to_gtk_snapshot(snapshot, doc_bounds, viewport);
let draw_stroke_elapsed = draw_stroke_start.elapsed();

snapshot.restore();
/*
let cairo_cx = snapshot.append_cairo(&graphene::Rect::from_p2d_aabb(surface_bounds));
Expand All @@ -192,8 +213,10 @@ impl Engine {
self.camera.image_scale(),
);
*/
let penholder_draw_start = SystemTime::now();
self.penholder
.draw_on_doc_to_gtk_snapshot(snapshot, &engine_view!(self))?;
let penholder_elapsed = penholder_draw_start.elapsed();

if self.config.read().visual_debug {
snapshot.save();
Expand All @@ -204,6 +227,25 @@ impl Engine {
visual_debug::draw_statistics_to_gtk_snapshot(snapshot, self, surface_bounds)?;
}

//stats
println!(
"Time for `draw_to_gtk_snapshot` : {:?}
snapshot setup {:?}
draw shadow {:?}
draw background {:?}
draw fmt {:?}
draw orig {:?}
draw stroke {:?}
penholder {:?}",
start_rendering.elapsed(),
elapsed_snapshot_setup,
draw_doc_shadow_elapsed,
draw_bgrd_elapsed,
draw_fmt_elapsed,
draw_orig_elapsed,
draw_stroke_elapsed,
penholder_elapsed
);
Ok(())
}

Expand Down Expand Up @@ -251,17 +293,23 @@ impl Engine {
snapshot.append_node(
gsk::ColorNode::new(
&gdk::RGBA::from_compose_color(self.document.config.background.color),
//&gdk::RGBA::RED,
&graphene::Rect::from_p2d_aabb(doc_bounds),
)
.upcast(),
);
snapshot.pop();

for r in self.background_rendernodes.iter() {
snapshot.append_node(r);
if let (Some(bounds), Some(render_node)) = (
self.origin_background_rendernode,
self.background_rendernode.clone(),
) {
snapshot.push_repeat(
&graphene::Rect::from_p2d_aabb(doc_bounds),
Some(&graphene::Rect::from_p2d_aabb(bounds)),
);
snapshot.append_node(render_node);
snapshot.pop();
}

snapshot.pop();
Ok(())
}

Expand Down
20 changes: 16 additions & 4 deletions crates/rnote-engine/src/engine/visual_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ pub(crate) fn draw_statistics_to_gtk_snapshot(
let text_bounds = Aabb::new(
na::point![
surface_bounds.maxs[0] - 320.0,
surface_bounds.mins[1] + 20.0
surface_bounds.mins[1] + 10.0
],
na::point![
surface_bounds.maxs[0] - 20.0,
surface_bounds.maxs[0] - 10.0,
surface_bounds.mins[1] + 120.0
],
);
Expand All @@ -157,21 +157,33 @@ pub(crate) fn draw_statistics_to_gtk_snapshot(
let strokes_total = engine.store.keys_unordered();
let strokes_in_viewport = engine
.store
.keys_unordered_intersecting_bounds(engine.camera.viewport());
.keys_unordered_intersecting_bounds(engine.camera.viewport()); // same as the call we do for rendering ?

let stroke_in_viewport_for_rendering = engine
.store
.stroke_keys_as_rendered_intersecting_bounds(engine.camera.viewport());

let selected_strokes = engine.store.selection_keys_unordered();
let trashed_strokes = engine.store.trashed_keys_unordered();
let strokes_hold_image = strokes_total
.iter()
.filter(|&&key| engine.store.holds_images(key))
.count();

let strokes_hold_rendernode = strokes_total
.iter()
.filter(|&&key| engine.store.hold_rendernode(key))
.count();

let statistics_text_string = format!(
"strokes in store: {}\nstrokes in current viewport: {}\nstrokes selected: {}\nstroke trashed: {}\nstrokes holding images: {}",
"strokes in store: {}\nstrokes in current viewport: {}\nstrokes selected: {}\nstroke trashed: {}\nstrokes holding images: {}\n strokes in the viewport for the rendering {} strokes holding rendernodes {}",
strokes_total.len(),
strokes_in_viewport.len(),
selected_strokes.len(),
trashed_strokes.len(),
strokes_hold_image,
stroke_in_viewport_for_rendering.len(), //verify we don't have much more things here
strokes_hold_rendernode,
);
let text_layout = piet_cx
.text()
Expand Down
Loading
Loading