Skip to main content

cranpose_render_common/graph/
inline_node.rs

1// A layout node drawn in its parent's layer.
2
3use std::cell::Cell;
4
5use cranpose_core::NodeId;
6use cranpose_ui::{Point, Rect, Size};
7
8use super::{
9    CONTAINED_DRAW_SLACK, LayerChange, ProjectiveTransform, RenderNode, inflate_rect,
10    nodes_draw_within, rect_within,
11};
12
13/// A layout node drawn into its parent's layer instead of a layer of its
14/// own, as Compose draws a node without a graphics layer into the display
15/// list of the layer above it: a leaf with no layer properties, pointer
16/// handling or window origins to publish. The scene matches it with its
17/// node as it matches a child layer, and a renderer places its content as it
18/// would place a child layer that only moves.
19#[derive(Clone, Default)]
20pub struct InlineNode {
21    /// Layout node drawn here.
22    pub node_id: NodeId,
23    /// The node's top left in its parent's layer: its placement and the
24    /// parent's content offset, where a layer of its own would lie.
25    pub origin: Point,
26    /// The node's size: its rect in its own space starts at the origin.
27    pub size: Size,
28    /// Whether the node lies in a motion context such as an animated scroll,
29    /// where a renderer must not snap its content rigidly to the pixel grid.
30    pub motion_context_animated: bool,
31    /// The number the node took when it last changed.
32    pub change: LayerChange,
33    /// The node's draws and text in draw order, in its own space: primitives
34    /// and draw runs only.
35    pub content: Vec<RenderNode>,
36    contained: Cell<Option<bool>>,
37    content_hash: Cell<Option<u64>>,
38}
39
40impl InlineNode {
41    /// The node's rect in its own space.
42    pub fn node_rect(&self) -> Rect {
43        Rect::from_size(self.size)
44    }
45
46    /// Maps the node's space to its parent layer's: a translation to
47    /// [`Self::origin`].
48    pub fn transform_to_parent(&self) -> ProjectiveTransform {
49        ProjectiveTransform::translation(self.origin.x, self.origin.y)
50    }
51
52    /// Whether everything the node draws lies within its rect, give or take
53    /// [`CONTAINED_DRAW_SLACK`], as [`super::LayerNode::draws_within_bounds`]
54    /// says of a layer. Worked out at the first call after a change.
55    pub fn draws_within_bounds(&self) -> bool {
56        if let Some(contained) = self.contained.get() {
57            return contained;
58        }
59        let contained = nodes_draw_within(
60            &self.content,
61            inflate_rect(self.node_rect(), CONTAINED_DRAW_SLACK),
62        );
63        self.contained.set(Some(contained));
64        contained
65    }
66
67    // Whether the node puts nothing outside `bounds` of its parent's layer.
68    pub(crate) fn draws_within_parent(&self, bounds: Rect) -> bool {
69        self.draws_within_bounds()
70            && rect_within(
71                inflate_rect(self.node_rect(), CONTAINED_DRAW_SLACK)
72                    .translate(self.origin.x, self.origin.y),
73                bounds,
74            )
75    }
76
77    // The hash of the node's content, worked out at the first call after a
78    // change: a layer above it hashes its own content again whenever it
79    // changes, as it reads a child layer's kept hash.
80    pub(crate) fn content_hash(&self) -> u64 {
81        if let Some(hash) = self.content_hash.get() {
82            return hash;
83        }
84        let hash = crate::graph_hash::inline_content_hash(self);
85        self.content_hash.set(Some(hash));
86        hash
87    }
88
89    // Takes a new change number after the node's content or place changed.
90    pub(crate) fn note_change(&mut self) {
91        self.change = LayerChange::next();
92        self.contained.set(None);
93        self.content_hash.set(None);
94    }
95}