Skip to content

Commit 05f36ee

Browse files
authored
Merge pull request #378 from kas-gui/work2
Async rendering for Svg widget
2 parents 440e5cd + d8e9dd1 commit 05f36ee

File tree

7 files changed

+224
-102
lines changed

7 files changed

+224
-102
lines changed

crates/kas-core/src/event/manager/mgr_pub.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,17 @@ impl EventState {
469469
self.hover_icon = icon;
470470
}
471471

472-
/// Push a message to the stack via a [`Future`]
472+
/// Asynchronously push a message to the stack via a [`Future`]
473473
///
474-
/// Expects a future which, on completion, returns a message.
475-
/// This message is then pushed to the message stack as if it were pushed
476-
/// with [`Self::push`] from widget `id`.
474+
/// The future is polled after event handling and after drawing and is able
475+
/// to wake the event loop. This future is executed on the main thread; for
476+
/// high-CPU tasks use [`Self::push_spawn`] instead.
477477
///
478-
/// The future will be polled before the event loop sleeps.
478+
/// The future must resolve to a message on completion. This message is
479+
/// pushed to the message stack as if it were pushed with [`EventMgr::push`]
480+
/// from widget `id`, allowing this widget or any ancestor to handle it in
481+
/// [`Widget::handle_message`].
482+
//
479483
// TODO: Can we identify the calling widget `id` via the context (EventMgr)?
480484
pub fn push_async<Fut, M>(&mut self, id: WidgetId, fut: Fut)
481485
where
@@ -485,13 +489,9 @@ impl EventState {
485489
self.push_async_erased(id, async { Erased::new(fut.await) });
486490
}
487491

488-
/// Push a type-erased message to the stack via a [`Future`]
492+
/// Asynchronously push a type-erased message to the stack via a [`Future`]
489493
///
490-
/// Expects a future which, on completion, returns a message.
491-
/// This message is then pushed to the message stack as if it were pushed
492-
/// with [`Self::push_erased`] from widget `id`.
493-
///
494-
/// The future will be polled before the event loop sleeps.
494+
/// This is a low-level variant of [`Self::push_async`].
495495
pub fn push_async_erased<Fut>(&mut self, id: WidgetId, fut: Fut)
496496
where
497497
Fut: IntoFuture<Output = Erased> + 'static,
@@ -502,14 +502,14 @@ impl EventState {
502502

503503
/// Spawn a task, run on a thread pool
504504
///
505-
/// This method is similar to [`Self::push_async`], except that the future
506-
/// is run on a worker thread (appropriate when significant CPU work is
507-
/// required).
508-
///
509-
/// The future will be spawned before the event loop sleeps.
505+
/// The future is spawned to a thread-pool before the event-handling loop
506+
/// sleeps, and is able to wake the loop on completion. Tasks involving
507+
/// significant CPU work should use this method over [`Self::push_async`].
510508
///
511-
/// Uses [`async-global-executor`].
512-
/// See crate documentation for configuration.
509+
/// This method is simply a wrapper around [`async_global_executor::spawn`]
510+
/// and [`Self::push_async`]; if a different multi-threaded executor is
511+
/// available, that may be used instead. See also [`async_global_executor`]
512+
/// documentation of configuration.
513513
#[cfg(feature = "spawn")]
514514
#[cfg_attr(doc_cfg, doc(cfg(feature = "spawn")))]
515515
pub fn push_spawn<Fut, M>(&mut self, id: WidgetId, fut: Fut)

crates/kas-resvg/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ svg = ["dep:resvg", "dep:usvg"]
2626
tiny-skia = { version = "0.8.2" }
2727
resvg = { version = "0.28.0", optional = true }
2828
usvg = { version = "0.28.0", optional = true }
29+
once_cell = "1.17.0"
30+
thiserror = "1.0.23"
2931

3032
[dependencies.kas]
3133
# We must rename this package since macros expect kas to be in scope:

crates/kas-resvg/src/canvas.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ pub trait CanvasProgram: std::fmt::Debug + Send + 'static {
1919
/// Draw image
2020
///
2121
/// This method should draw an image to the canvas. It is called when the
22-
/// pixmap is created and resized, when [`Canvas::redraw`] is called, and
23-
/// when requested by [`CanvasProgram::do_redraw_animate`].
22+
/// pixmap is created and resized and when requested by [`Self::need_redraw`].
23+
///
24+
/// Note that [`Layout::draw`] does not call this method, but instead draws
25+
/// from a copy of the `pixmap` (updated each time this method completes).
2426
fn draw(&mut self, pixmap: &mut Pixmap);
2527

2628
/// This method is called each time a frame is drawn. Note that since
@@ -88,18 +90,13 @@ impl<P: CanvasProgram> State<P> {
8890
impl_scope! {
8991
/// A canvas widget over the `tiny-skia` library
9092
///
93+
/// The widget is essentially a cached image drawn from a [`Pixmap`]
94+
/// controlled through an implementation of [`CanvasProgram`].
9195
/// Note that the `tiny-skia` API is re-exported as [`crate::tiny_skia`].
9296
///
93-
/// Canvas size is controlled by the sizing arguments passed to the constructor,
94-
/// as well as the `stretch` factor and the display's scale factor `sf`.
95-
/// Minimum size is `min_size * sf`. Ideal size is `ideal_size * sf` except that
96-
/// if `fix_aspect` is true, then the ideal height is the one that preserves
97-
/// aspect ratio for the given width. The canvas may also exceed the ideal size
98-
/// if a [`Stretch`] factor greater than `None` is used.
99-
///
100-
/// The canvas (re)creates the backing pixmap when the size is set and draws
101-
/// to the new pixmap immediately. If the canvas program is modified then
102-
/// [`Canvas::redraw`] must be called to update the pixmap.
97+
/// By default, a `Canvas` has a minimum size of 128x128 pixels and a high
98+
/// stretch factor (i.e. will greedily occupy extra space). To adjust this
99+
/// call one of the sizing/scaling methods.
103100
#[autoimpl(Debug ignore self.inner)]
104101
#[derive(Clone)]
105102
#[widget]

0 commit comments

Comments
 (0)