1use crate::graph::{
5 CachePolicy, DrawPrimitiveNode, IsolationReasons, LayerNode, PrimitiveEntry, PrimitiveNode,
6 PrimitivePhase, ProjectiveTransform, RenderGraph, RenderNode, TextPrimitiveNode,
7};
8use crate::raster_cache::LayerRasterCacheHashes;
9use cranpose_ui_graphics::{
10 Brush, Color, CornerRadii, DrawPrimitive, GraphicsLayer, Point, Rect, Size,
11};
12
13#[derive(Clone, PartialEq, Eq)]
16pub struct DevOverlayKey {
17 pub text: String,
18 pub viewport_width_bits: u32,
19 pub viewport_height_bits: u32,
20}
21
22impl DevOverlayKey {
23 pub fn new(text: &str, viewport: Size) -> Self {
24 Self {
25 text: text.to_string(),
26 viewport_width_bits: viewport.width.to_bits(),
27 viewport_height_bits: viewport.height.to_bits(),
28 }
29 }
30}
31
32pub fn build_dev_overlay_graph(
36 text: &str,
37 viewport: Size,
38 node_id: cranpose_core::NodeId,
39) -> RenderGraph {
40 let padding = 8.0;
41 let font_size = 14.0;
42 let char_width = 7.0;
43 let text_width = text.len() as f32 * char_width;
44 let text_height = font_size * 1.4;
45 let x = (viewport.width - text_width - padding * 2.0).max(padding);
46 let y = padding;
47
48 let mut overlay_layer = LayerNode {
49 node_id: Some(node_id),
50 local_bounds: Rect {
51 x: 0.0,
52 y: 0.0,
53 width: text_width + padding,
54 height: text_height + padding / 2.0,
55 },
56 transform_to_parent: ProjectiveTransform::translation(x, y),
57 content_offset: Point::default(),
58 motion_context_animated: false,
59 translated_content_context: false,
60 translated_content_offset: Point::default(),
61 scene_children_origin: Point::default(),
62 scene_children_layer_translation: Point::default(),
63 graphics_layer: GraphicsLayer::default(),
64 clip_to_bounds: false,
65 shadow_clip: None,
66 hit_test: None,
67 has_hit_targets: false,
68 isolation: IsolationReasons::default(),
69 cache_policy: CachePolicy::None,
70 cache_hashes: LayerRasterCacheHashes::default(),
71 cache_hashes_valid: false,
72 children: vec![
73 RenderNode::Primitive(PrimitiveEntry {
74 phase: PrimitivePhase::BeforeChildren,
75 node: PrimitiveNode::Draw(DrawPrimitiveNode {
76 primitive: DrawPrimitive::RoundRect {
77 rect: Rect {
78 x: 0.0,
79 y: 0.0,
80 width: text_width + padding,
81 height: text_height + padding / 2.0,
82 },
83 brush: Brush::Solid(Color(0.0, 0.0, 0.0, 0.7)),
84 radii: CornerRadii::uniform(4.0),
85 stroke: None,
86 },
87 clip: None,
88 }),
89 }),
90 RenderNode::Primitive(PrimitiveEntry {
91 phase: PrimitivePhase::AfterChildren,
92 node: PrimitiveNode::Text(Box::new(TextPrimitiveNode {
93 node_id,
94 rect: Rect {
95 x: padding / 2.0,
96 y: padding / 4.0,
97 width: text_width,
98 height: text_height,
99 },
100 text: std::rc::Rc::new(cranpose_ui::text::AnnotatedString::from(text)),
101 text_style: cranpose_ui::TextStyle::default(),
102 font_size,
103 layout_options: cranpose_ui::TextLayoutOptions::default(),
104 clip: None,
105 })),
106 }),
107 ],
108 };
109 overlay_layer.recompute_raster_cache_hashes();
110
111 let mut graph = RenderGraph::new(LayerNode {
112 node_id: None,
113 local_bounds: Rect::from_size(viewport),
114 transform_to_parent: ProjectiveTransform::identity(),
115 content_offset: Point::default(),
116 motion_context_animated: false,
117 translated_content_context: false,
118 translated_content_offset: Point::default(),
119 scene_children_origin: Point::default(),
120 scene_children_layer_translation: Point::default(),
121 graphics_layer: GraphicsLayer::default(),
122 clip_to_bounds: false,
123 shadow_clip: None,
124 hit_test: None,
125 has_hit_targets: false,
126 isolation: IsolationReasons::default(),
127 cache_policy: CachePolicy::None,
128 cache_hashes: LayerRasterCacheHashes::default(),
129 cache_hashes_valid: false,
130 children: vec![RenderNode::Layer(Box::new(overlay_layer))],
131 });
132 graph.root.recompute_raster_cache_hashes();
133 graph
134}