ferroui_base/rendering/composition/drawing/
render_data_resources.rs1use super::IRenderDataGeometry;
2use crate::media::{IBrush, IPen};
3use crate::platform::{IGeometryImpl, IGlyphRunImpl};
4use crate::rendering::composition::server::ServerObjectId;
5use crate::rendering::scene_graph::ICustomDrawOperation;
6use std::collections::HashMap;
7use std::rc::Rc;
8use std::sync::Arc;
9
10pub const NULL_HANDLE: i32 = -1;
12
13#[derive(Clone)]
20pub enum RenderDataResource {
21 Brush(Rc<dyn IBrush>),
22 Pen(Rc<dyn IPen>),
23 GeometryImpl(Arc<dyn IGeometryImpl>),
24 Geometry(Rc<dyn IRenderDataGeometry>),
25 GlyphRun(Arc<Arc<dyn IGlyphRunImpl>>),
30 Bitmap(Arc<crate::utilities::RefCounted<crate::platform::SharedBitmapImpl>>),
33 CustomDrawOperation(std::sync::Arc<dyn ICustomDrawOperation>),
34 Effect(Arc<dyn crate::media::IImmutableEffect>),
35 ServerBrush { server: ServerObjectId, client: Rc<dyn IBrush> },
36 ServerPen { server: ServerObjectId, client: Rc<dyn IPen> },
37 ServerGeometry { server: ServerObjectId, client: Rc<dyn IRenderDataGeometry> },
38 ClientPen(Rc<dyn IPen>),
41 NotSent,
43}
44
45#[derive(Clone, Copy, PartialEq, Eq, Hash)]
46enum Kind {
47 Brush,
48 Pen,
49 GeometryImpl,
50 Geometry,
51 GlyphRun,
52 Bitmap,
53 Custom,
54 Effect,
55 Server,
56}
57
58impl RenderDataResource {
59 fn key(&self) -> (Kind, usize) {
62 fn address<T: ?Sized>(rc: &Rc<T>) -> usize {
63 Rc::as_ptr(rc) as *const () as usize
64 }
65 match self {
66 RenderDataResource::Brush(v) => (Kind::Brush, address(v)),
67 RenderDataResource::Pen(v) | RenderDataResource::ClientPen(v) => (Kind::Pen, address(v)),
68 RenderDataResource::GeometryImpl(v) => (Kind::GeometryImpl, std::sync::Arc::as_ptr(v) as *const () as usize),
69 RenderDataResource::Geometry(v) => (Kind::Geometry, address(v)),
70 RenderDataResource::GlyphRun(v) => (Kind::GlyphRun, Arc::as_ptr(v) as *const () as usize),
71 RenderDataResource::Bitmap(v) => (Kind::Bitmap, Arc::as_ptr(v) as *const () as usize),
72 RenderDataResource::CustomDrawOperation(v) => (Kind::Custom, Arc::as_ptr(v) as *const () as usize),
73 RenderDataResource::Effect(v) => (Kind::Effect, Arc::as_ptr(v) as *const () as usize),
74 RenderDataResource::ServerBrush { server, .. }
75 | RenderDataResource::ServerPen { server, .. }
76 | RenderDataResource::ServerGeometry { server, .. } => (Kind::Server, server.index()),
77 RenderDataResource::NotSent => (Kind::Server, usize::MAX),
78 }
79 }
80}
81
82#[derive(Default)]
85pub struct RenderDataResources {
86 resources: Vec<RenderDataResource>,
87 intern_map: Option<HashMap<(Kind, usize), i32>>,
88}
89
90impl RenderDataResources {
91 pub fn count(&self) -> usize {
92 self.resources.len()
93 }
94
95 pub fn intern(&mut self, resource: Option<RenderDataResource>) -> i32 {
98 let Some(resource) = resource else { return NULL_HANDLE };
99 let key = resource.key();
100 let intern_map = self.intern_map.get_or_insert_with(HashMap::new);
101 if let Some(handle) = intern_map.get(&key) {
102 return *handle;
103 }
104 let handle = self.resources.len() as i32;
105 self.resources.push(resource);
106 intern_map.insert(key, handle);
107 handle
108 }
109
110 pub fn append_deserialized(&mut self, resource: RenderDataResource) -> i32 {
113 let handle = self.resources.len() as i32;
114 self.resources.push(resource);
115 handle
116 }
117
118 pub fn get(&self, handle: i32) -> Option<&RenderDataResource> {
120 if handle == NULL_HANDLE {
121 None
122 } else {
123 Some(&self.resources[handle as usize])
124 }
125 }
126
127 pub fn iter(&self) -> impl Iterator<Item = &RenderDataResource> {
128 self.resources.iter()
129 }
130
131 pub fn brush(&self, handle: i32) -> Option<&dyn IBrush> {
132 match self.get(handle)? {
133 RenderDataResource::Brush(brush) | RenderDataResource::ServerBrush { client: brush, .. } => Some(&**brush),
134 _ => panic!("the render data resource is not a brush"),
135 }
136 }
137
138 pub fn pen(&self, handle: i32) -> Option<&dyn IPen> {
139 match self.get(handle)? {
140 RenderDataResource::Pen(pen)
141 | RenderDataResource::ClientPen(pen)
142 | RenderDataResource::ServerPen { client: pen, .. } => Some(&**pen),
143 RenderDataResource::NotSent => None,
144 _ => panic!("the render data resource is not a pen"),
145 }
146 }
147
148 pub fn geometry_impl(&self, handle: i32) -> Option<Arc<dyn IGeometryImpl>> {
149 match self.get(handle)? {
150 RenderDataResource::GeometryImpl(geometry) => Some(geometry.clone()),
151 RenderDataResource::Geometry(geometry) | RenderDataResource::ServerGeometry { client: geometry, .. } => {
152 geometry.geometry_impl()
153 }
154 _ => panic!("the render data resource is not a geometry"),
155 }
156 }
157
158 pub fn glyph_run(&self, handle: i32) -> Option<&std::sync::Arc<dyn IGlyphRunImpl>> {
159 match self.get(handle)? {
160 RenderDataResource::GlyphRun(glyph_run) => Some(&**glyph_run),
161 _ => panic!("the render data resource is not a glyph run"),
162 }
163 }
164
165 pub fn bitmap(&self, handle: i32) -> Option<std::sync::Arc<crate::platform::SharedBitmapImpl>> {
166 match self.get(handle)? {
167 RenderDataResource::Bitmap(bitmap) => Some(bitmap.item()),
168 _ => panic!("the render data resource is not a bitmap"),
169 }
170 }
171
172 pub fn custom_draw_operation(&self, handle: i32) -> Option<&std::sync::Arc<dyn ICustomDrawOperation>> {
173 match self.get(handle)? {
174 RenderDataResource::CustomDrawOperation(operation) => Some(operation),
175 _ => panic!("the render data resource is not a custom draw operation"),
176 }
177 }
178
179 pub fn effect(&self, handle: i32) -> Option<&Arc<dyn crate::media::IImmutableEffect>> {
180 match self.get(handle)? {
181 RenderDataResource::Effect(effect) => Some(effect),
182 _ => panic!("the render data resource is not an effect"),
183 }
184 }
185
186 pub fn dispose(&mut self) {
188 self.resources.clear();
189 self.intern_map = None;
190 }
191}