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
//! Layout-to-renderer pipe for [Cotis](https://crates.io/crates/cotis).
//!
//! `cotis-pipes` implements [`cotis::pipes::LayoutRenderPipe`] — the conversion layer between
//! [`cotis-layout`](https://crates.io/crates/cotis-layout) output and
//! [`cotis-defaults`](https://crates.io/crates/cotis-defaults) render commands. Each frame,
//! layout produces a stream of [`RenderCommandOutput`](cotis_layout::layout_struct::RenderCommandOutput)
//! values; this crate decodes them into a caller-chosen [`RenderTList`](cotis_defaults::render_commands::render_t_list::RenderTList)
//! command stream for the renderer.
//!
//! # Frame pipeline
//!
//! ```text
//! cotis-layout → cotis-pipes → renderer
//! RenderCommandOutput RenderTList<…> CotisRenderer::draw
//! ```
//!
//! 1. [`CotisLayoutManager`](cotis_layout::preamble::CotisLayoutManager) runs layout and yields
//! [`RenderCommandOutput`](cotis_layout::layout_struct::RenderCommandOutput) per frame.
//! 2. [`CotisLayoutToRenderListPipeForGenerics`](cotis_layout_pipes::CotisLayoutToRenderListPipeForGenerics)
//! walks your `RenderTList` type and emits draw commands (`Rectangle`, `Text`, `Border`,
//! `Image`, `ClipStart`, `ClipEnd`, plus any custom types you register).
//! 3. The renderer consumes the flattened `RenderTList` stream.
//!
//! When layout output already matches what the renderer expects, pass [`()`] as the identity
//! [`LayoutRenderPipe`](cotis::pipes::LayoutRenderPipe) instead (see
//! [`CotisApp::new`](cotis::cotis_app::CotisApp::new)).
//!
//! # Quick start
//!
//! Define a [`RenderTList`](cotis_defaults::render_commands::render_t_list::RenderTList) type
//! alias for your command stream, then wire the pipe into [`CotisApp`](cotis::cotis_app::CotisApp):
//!
//! ```rust,ignore
//! use cotis::cotis_app::CotisApp;
//! use cotis_layout::preamble::CotisLayoutManager;
//! use cotis_pipes::cotis_layout_pipes::CotisLayoutToRenderListPipeForGenerics;
//! use cotis_defaults::render_commands::render_t_list::RenderTList;
//! use cotis_defaults::render_commands::{ClipStart, ClipEnd, Rectangle, Border, Text};
//! use cotis_utils::math::Dimensions;
//!
//! type StandardRenderCmds = RenderTList<
//! ClipStart<'static, ()>,
//! RenderTList<
//! ClipEnd,
//! RenderTList<
//! Rectangle<'static, ()>,
//! RenderTList<Border<'static, ()>, RenderTList<Text<'static, ()>, ()>>,
//! >,
//! >,
//! >;
//!
//! let dimensions = Dimensions::new(800.0, 600.0);
//! let manager = CotisLayoutManager::new(dimensions);
//! // let app = CotisApp::new(renderer, manager, CotisLayoutToRenderListPipeForGenerics);
//! ```
//!
//! See [`cotis-layout` examples](https://github.com/igna-778/cotis-layout/tree/main/examples)
//! — especially `support.rs` for a complete `StandardRenderCmds` alias and
//! `circle_example.rs` for extending the pipeline with custom drawables.
//!
//! # Extending with custom drawables
//!
//! Append your type to the tail of a `RenderTList` and implement
//! [`FromRenderCommandOutput`](cotis_layout_pipes::FromRenderCommandOutput). Return `Some(cmd)`
//! to emit a draw command or `None` to skip. See
//! [`cotis_layout_pipes`] for decode rules and the extension model.
//!
//! # Modules
//!
//! - [`cotis_layout_pipes`] — pipe implementation, decode traits, and built-in command decoders.