1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! A native Rust GUI library with a retained widget tree, fine-grained
//! reactive signals and damage-tracked repainting, built to stay fast on
//! machines without a usable GPU.
//!
//! # Quick start
//!
//! A counter: a button and a label bound to one signal. Each press writes the
//! signal, the label's text closure reruns, and the next frame repaints only
//! the label.
//!
//! ```no_run
//! use smudge::prelude::*;
//!
//! fn main() -> Result<(), PlatformError> {
//! let count = RwSignal::new(0_u32);
//! let press = count.clone();
//! let shown = count.clone();
//!
//! run(
//! WindowOptions {
//! title: String::from("Counter"),
//! size: Size {
//! width: 280.0,
//! height: 140.0,
//! },
//! clear_color: Color::rgb(16, 17, 21),
//! repaint: Default::default(),
//! show_damage: false,
//! renderer: RendererChoice::default(),
//! stats: None,
//! on_frame: None,
//! on_event: None,
//! frame_limit: None,
//! },
//! move || {
//! column()
//! .padding(px(24.0))
//! .gap(Size {
//! width: 0.0,
//! height: 12.0,
//! })
//! .align_items(Align::Center)
//! .child(
//! button("Count up")
//! .primary()
//! .on_press(move || press.update(|count| *count += 1)),
//! )
//! .child(label(move || format!("Clicked {} times", shown.get())))
//! },
//! )
//! }
//! ```
//!
//! The runnable versions of this and two larger applications live in
//! `crates/smudge/examples`. The same application also runs headless:
//! [`core::App`] takes the build closure, and its `frame` method advances it
//! one frame at a time, which is what tests and benchmarks drive.
//!
//! # The frame model
//!
//! Application state lives in signals ([`core::reactive::RwSignal`]). Styling
//! a widget with a closure, or handing a closure to [`text::label`], binds
//! that part of the widget to the signals the closure reads. A write to a
//! signal touches no widget directly. At the next `App::frame`, the rerun
//! bindings queue their updates, layout reruns for the nodes the updates
//! marked, the changed widgets regenerate their paint operations, and the
//! pipeline subtracts what stayed the same. What is left is the frame's
//! damage, the physical-pixel rectangles the frame changed, and the renderer
//! repaints exactly that onto the previous frame's pixels. A frame that
//! changes one small box rasterizes and presents one small box;
//! [`core::RepaintMode::Full`] turns the subtraction off when a
//! whole-surface redraw is wanted instead.
//!
//! # Platform support
//!
//! - **Desktop:** the CPU renderer presents through the window's buffer. With
//! the `gpu` feature, a vello renderer draws the same display list on the
//! GPU, and [`window::RendererChoice::Auto`], the default, uses the GPU
//! only when the adapter is a real GPU, falling back to the CPU renderer on
//! a software rasterizer.
//! - **Web:** the CPU renderer runs in a browser on `wasm32-unknown-unknown`;
//! `crates/smudge-platform/examples/web` holds a buildable web example.
//! - **Accessibility:** the AccessKit projection runs on desktop only. The
//! web target has no accessibility backend in this version.
//! - **Text:** Chinese, Japanese, Thai, Lao, Khmer and Burmese break by word
//! only with the `complex-scripts` feature, which compiles in the break
//! dictionaries at about 3 MB per binary.
pub use smudge_core as core;
pub use smudge_text as text;
pub use smudge_widgets as widgets;
pub use smudge_platform as window;
pub use smudge_gpu as gpu;