alpha2_engine/layout/
draw.rs1use super::paint::{PaintItem, Placement};
5use crate::TextTexture;
6use alpha2_render::{
7 BlendMode, GraphError, GraphLayer, LayerTransform, RenderError, RenderGraph, RenderNodeId,
8 RenderSize,
9};
10use std::sync::Arc;
11
12#[derive(Debug)]
18pub struct PreparedLayout {
19 pub(crate) items: Vec<PaintItem>,
20 pub(crate) texts: Vec<Option<u64>>,
21}
22
23#[derive(Clone, Debug)]
25pub(crate) struct LaidOut<'t> {
26 pub(crate) layout: Arc<PreparedLayout>,
27 pub(crate) texts: Vec<Option<TextTexture<'t>>>,
28}
29
30impl<'t> LaidOut<'t> {
31 pub(crate) fn attach(
34 layout: Arc<PreparedLayout>,
35 frames: &'t dyn crate::FrameProvider,
36 ) -> Option<Self> {
37 let texts = layout
38 .texts
39 .iter()
40 .map(|key| {
41 key.map(|key| frames.text(key))
42 .map_or(Some(None), |text| text.map(Some))
43 })
44 .collect::<Option<Vec<_>>>()?;
45 Some(Self { layout, texts })
46 }
47
48 pub(crate) fn add_to(&self, graph: &mut RenderGraph<'t>) -> Result<RenderNodeId, RenderError> {
50 let layers = self.layers(graph, &self.layout.items)?;
51 graph
52 .add_composite(layers)
53 .map_err(GraphError::into_render_error)
54 }
55
56 fn layers(
57 &self,
58 graph: &mut RenderGraph<'t>,
59 items: &[PaintItem],
60 ) -> Result<Vec<GraphLayer>, RenderError> {
61 let size = graph.size();
62 let canvas = [size.width, size.height];
63 let mut layers = Vec::with_capacity(items.len());
64 for item in items {
65 let (source, place, extent) = match item {
66 PaintItem::Vector { scene, place } => {
67 (graph.add_vector(Arc::clone(scene)), *place, canvas)
68 }
69 PaintItem::Text { index, place } => {
70 let texture = self
71 .texts
72 .get(*index)
73 .copied()
74 .flatten()
75 .ok_or(RenderError::MissingText)?;
76 let source = match texture.cache_key {
77 Some(key) => graph.add_source_with_key(texture.texture, key),
78 None => graph.add_source(texture.texture),
79 };
80 (source, *place, [texture.width, texture.height])
81 }
82 PaintItem::Group { items, clip, place } => {
83 let inner = self.layers(graph, items)?;
84 let mut node = graph
85 .add_composite(inner)
86 .map_err(GraphError::into_render_error)?;
87 if let Some(clip) = clip {
88 let coverage = graph.add_vector(Arc::clone(clip));
89 node = crate::frame::coverage_mask(
90 graph,
91 node,
92 &[(coverage, false, alpha2_model::MaskMode::Add)],
93 )?;
94 }
95 (node, *place, canvas)
96 }
97 };
98 layers.push(GraphLayer {
99 source,
100 visual: layer_transform(place, extent, size),
101 blend_mode: BlendMode::Normal,
102 });
103 }
104 Ok(layers)
105 }
106}
107
108#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
111fn layer_transform(place: Placement, extent: [u32; 2], size: RenderSize) -> LayerTransform {
112 let output = [f64::from(size.width), f64::from(size.height)];
113 let extent = extent.map(f64::from);
114 LayerTransform {
115 position: [
116 (place.position[0] / output[0]) as f32,
117 (place.position[1] / output[1]) as f32,
118 ],
119 anchor: [
120 (place.anchor[0] / extent[0]) as f32,
121 (place.anchor[1] / extent[1]) as f32,
122 ],
123 scale: [
124 (place.scale[0] * extent[0] / output[0]) as f32,
125 (place.scale[1] * extent[1] / output[1]) as f32,
126 ],
127 rotation_degrees: place.rotation_degrees as f32,
128 opacity: place.opacity,
129 }
130}