Skip to main content

devpage_design/display/
trees.rs

1//! The property trees: transform, clip and effect nodes in arenas whose
2//! slots are reused. A command names its clip and effect; its chunk names
3//! its transform.
4
5use kurbo::{BezPath, Vec2};
6
7/// A node in one of the property trees, by its slot.
8pub type Id = u32;
9
10/// A scene node's place: its offset from its parent's — or, for a child of
11/// a [run](super::Run), the run's place for it, read from the run's prefix
12/// sums whenever it is asked for, so a sibling's change of size moves it
13/// without touching it.
14#[derive(Clone, Debug)]
15pub struct Transform {
16    pub parent: Option<Id>,
17    pub offset: Vec2,
18    pub item: Option<(super::RunId, crate::tree::OrderKey)>,
19}
20
21/// A clipping shape, in the coordinates of its transform node.
22#[derive(Clone)]
23pub struct Clip {
24    pub parent: Option<Id>,
25    pub transform: Id,
26    pub path: BezPath,
27}
28
29/// How an effect's layer meets what is under it.
30#[derive(Clone, Copy, Debug, PartialEq)]
31pub enum Blend {
32    /// Drawn over it at an opacity.
33    Opacity(f32),
34    /// Added to it, color and alpha alike, so two fills in such layers that
35    /// meet edge to edge sum to exactly what is in them, with no seam.
36    Add,
37}
38
39/// A layer: its blend, the bound nothing in it reaches — in its transform's
40/// coordinates, or, when `None`, the whole area being painted — and the clip
41/// it is drawn inside.
42#[derive(Clone)]
43pub struct Effect {
44    pub parent: Option<Id>,
45    pub clip: Id,
46    pub transform: Id,
47    pub blend: Blend,
48    pub bounds: Option<BezPath>,
49}
50
51/// A store of property-tree nodes whose slots are reused.
52#[derive(Clone)]
53pub struct Arena<T> {
54    pub(super) slots: Vec<Option<T>>,
55    pub(super) free: Vec<Id>,
56}
57
58impl<T> Default for Arena<T> {
59    fn default() -> Self {
60        Arena {
61            slots: Vec::new(),
62            free: Vec::new(),
63        }
64    }
65}
66
67impl<T> Arena<T> {
68    pub fn add(&mut self, t: T) -> Id {
69        match self.free.pop() {
70            Some(id) => {
71                self.slots[id as usize] = Some(t);
72                id
73            }
74            None => {
75                self.slots.push(Some(t));
76                (self.slots.len() - 1) as Id
77            }
78        }
79    }
80
81    pub fn remove(&mut self, id: Id) {
82        if self
83            .slots
84            .get_mut(id as usize)
85            .and_then(Option::take)
86            .is_some()
87        {
88            self.free.push(id);
89        }
90    }
91
92    /// How many nodes are live.
93    pub fn live(&self) -> usize {
94        self.slots.len() - self.free.len()
95    }
96
97    pub fn get(&self, id: Id) -> &T {
98        self.slots[id as usize].as_ref().expect("a live node")
99    }
100
101    pub fn get_mut(&mut self, id: Id) -> &mut T {
102        self.slots[id as usize].as_mut().expect("a live node")
103    }
104}
105
106/// The three property trees.
107#[derive(Clone, Default)]
108pub struct Trees {
109    pub transforms: Arena<Transform>,
110    pub clips: Arena<Clip>,
111    pub effects: Arena<Effect>,
112}