densa_draw/lib.rs
1//! A frame's display list, independent of any GPU API.
2//!
3//! Painters draw through a [`Canvas`]: filled rectangles and glyphs (from a shared
4//! `densa_text::GlyphCache`) become [`Instance`]s in an [`InstanceBuffer`], one quad each, in
5//! the vertex layout `densa-render` uploads and draws in a single instanced draw call. Keeping
6//! the list GPU-free makes every painter testable without a GPU, and lets other backends
7//! draw the same list.
8//!
9//! Drawing allocates nothing once the frame's glyphs are cached.
10//!
11//! ```
12//! use densa_draw::{Canvas, Color, InstanceBuffer, Rect};
13//! use densa_text::{AtlasConfig, GlyphCache};
14//!
15//! // One glyph cache and one instance buffer per frame loop, reused every frame.
16//! let mut cache = GlyphCache::new(AtlasConfig::default());
17//! let mut instances = InstanceBuffer::with_capacity(1024);
18//!
19//! let mut canvas = Canvas::begin(&mut cache, &mut instances);
20//! canvas.fill_rect(Rect::new(0.0, 0.0, 200.0, 20.0), Color::srgb(0x202020));
21//! let saved = canvas.state();
22//! canvas.clip(Rect::new(0.0, 0.0, 100.0, 100.0));
23//! // Cut to the clip on the CPU: the frame stays one draw call.
24//! canvas.fill_rect(Rect::new(50.0, 0.0, 200.0, 20.0), Color::WHITE);
25//! canvas.restore(saved);
26//!
27//! assert_eq!(instances.len(), 2);
28//! let cut = instances.as_slice()[1];
29//! assert_eq!(cut.rect, [50.0, 0.0, 50.0, 20.0]); // x, y, width, height
30//! ```
31
32mod canvas;
33mod instance;
34
35pub use canvas::{Canvas, CanvasState};
36pub use densa_core::{Color, Point, Rect, Size};
37pub use instance::{Instance, InstanceBuffer};