1use super::{
6 DrawBitmapPayload, DrawCustomPayload, DrawEllipsePayload, DrawGeometryPayload, DrawGlyphRunPayload,
7 DrawLinePayload, DrawRectanglePayload, IRenderDataVisitor, PushClipPayload,
8 PushEffectPayload, PushGeometryClipPayload, PushOpacityMaskPayload, PushOpacityPayload,
9 PushRenderOptionsPayload, PushTextOptionsPayload, PushTransformPayload, RenderDataOpcode, RenderDataReader,
10 RenderDataResource, RenderDataResources, RenderDataWriter,
11};
12use crate::media::{BoxShadow, BoxShadows, RenderOptions, TextOptions};
13use crate::platform::IGlyphRunImpl;
14use crate::rendering::composition::server::{IServerObject, ServerObjectId};
15use crate::rendering::composition::transport::{BatchObject, BatchStreamReader, BatchStreamWriter};
16use crate::rendering::scene_graph::ICustomDrawOperation;
17use crate::{Matrix, Point, Rect, RoundedRect};
18use std::rc::Rc;
19use std::sync::Arc;
20
21const TAG_NOT_SENT: u8 = 0;
22const TAG_BRUSH: u8 = 1;
23const TAG_PEN: u8 = 2;
24const TAG_GEOMETRY_IMPL: u8 = 3;
25const TAG_GLYPH_RUN: u8 = 5;
27const TAG_BITMAP: u8 = 6;
28const TAG_CUSTOM: u8 = 7;
29const TAG_EFFECT: u8 = 8;
30const TAG_SERVER_BRUSH: u8 = 9;
31const TAG_SERVER_PEN: u8 = 10;
32const TAG_SERVER_GEOMETRY: u8 = 11;
33
34#[derive(Default)]
36pub struct RenderDataStream {
37 writer: RenderDataWriter,
38 pub(super) resources: RenderDataResources,
39 depth: i32,
40 max_depth: i32,
41}
42
43impl RenderDataStream {
44 pub fn new() -> Self {
45 Self::default()
46 }
47
48 pub fn opcodes(&self) -> &[u8] {
50 self.writer.written()
51 }
52
53 pub fn opcode_length(&self) -> usize {
56 self.writer.length()
57 }
58
59 pub fn depth(&self) -> i32 {
61 self.depth
62 }
63
64 pub fn max_depth(&self) -> i32 {
66 self.max_depth
67 }
68
69 pub fn resource_count(&self) -> usize {
70 self.resources.count()
71 }
72
73 pub fn get_resource(&self, handle: i32) -> Option<&RenderDataResource> {
74 self.resources.get(handle)
75 }
76
77 pub fn rewind(&mut self, length: usize, depth: i32) {
80 self.writer.rewind(length);
81 self.depth = depth;
82 }
83
84 fn enter_scope(&mut self) {
85 self.depth += 1;
86 if self.depth > self.max_depth {
87 self.max_depth = self.depth;
88 }
89 }
90
91 pub fn dispose_resources(&self) {
94 for resource in self.resources.iter() {
95 if let RenderDataResource::CustomDrawOperation(operation) = resource {
96 operation.dispose();
97 }
98 }
99 }
100
101 pub fn draw_line(
102 &mut self,
103 server_pen: Option<RenderDataResource>,
104 client_pen: Option<RenderDataResource>,
105 p1: Point,
106 p2: Point,
107 ) {
108 let payload = DrawLinePayload {
109 server_pen: self.resources.intern(server_pen),
110 client_pen: self.resources.intern(client_pen),
111 p1,
112 p2,
113 };
114 self.writer.write_payload(payload);
115 }
116
117 pub fn draw_rectangle(
118 &mut self,
119 server_brush: Option<RenderDataResource>,
120 server_pen: Option<RenderDataResource>,
121 client_pen: Option<RenderDataResource>,
122 rect: RoundedRect,
123 box_shadows: &BoxShadows,
124 ) {
125 let payload = DrawRectanglePayload {
126 server_brush: self.resources.intern(server_brush),
127 server_pen: self.resources.intern(server_pen),
128 client_pen: self.resources.intern(client_pen),
129 rect,
130 box_shadow_count: box_shadows.count() as i32,
131 };
132 self.writer.write_payload(payload);
133 for shadow in box_shadows.iter() {
134 self.writer.write(shadow);
135 }
136 }
137
138 pub fn draw_ellipse(
139 &mut self,
140 server_brush: Option<RenderDataResource>,
141 server_pen: Option<RenderDataResource>,
142 client_pen: Option<RenderDataResource>,
143 rect: Rect,
144 ) {
145 let payload = DrawEllipsePayload {
146 server_brush: self.resources.intern(server_brush),
147 server_pen: self.resources.intern(server_pen),
148 client_pen: self.resources.intern(client_pen),
149 rect,
150 };
151 self.writer.write_payload(payload);
152 }
153
154 pub fn draw_geometry(
155 &mut self,
156 server_brush: Option<RenderDataResource>,
157 server_pen: Option<RenderDataResource>,
158 client_pen: Option<RenderDataResource>,
159 geometry: Option<RenderDataResource>,
160 ) {
161 let payload = DrawGeometryPayload {
162 server_brush: self.resources.intern(server_brush),
163 server_pen: self.resources.intern(server_pen),
164 client_pen: self.resources.intern(client_pen),
165 geometry: self.resources.intern(geometry),
166 };
167 self.writer.write_payload(payload);
168 }
169
170 pub fn draw_glyph_run(
173 &mut self,
174 server_brush: Option<RenderDataResource>,
175 glyph_run: Option<std::sync::Arc<dyn IGlyphRunImpl>>,
176 ) {
177 let glyph_run = glyph_run.map(|glyph_run| RenderDataResource::GlyphRun(Arc::new(glyph_run)));
178 let payload = DrawGlyphRunPayload {
179 server_brush: self.resources.intern(server_brush),
180 glyph_run: self.resources.intern(glyph_run),
181 };
182 self.writer.write_payload(payload);
183 }
184
185 pub fn draw_bitmap(
188 &mut self,
189 bitmap: Option<crate::utilities::RefCounted<crate::platform::SharedBitmapImpl>>,
190 opacity: f64,
191 source_rect: Rect,
192 dest_rect: Rect,
193 ) {
194 let bitmap = bitmap.map(|bitmap| RenderDataResource::Bitmap(Arc::new(bitmap)));
195 let payload = DrawBitmapPayload {
196 bitmap: self.resources.intern(bitmap),
197 opacity,
198 source_rect,
199 dest_rect,
200 };
201 self.writer.write_payload(payload);
202 }
203
204 pub fn draw_custom(&mut self, operation: Option<std::sync::Arc<dyn ICustomDrawOperation>>) {
205 let payload = DrawCustomPayload {
206 operation: self.resources.intern(operation.map(RenderDataResource::CustomDrawOperation)),
207 };
208 self.writer.write_payload(payload);
209 }
210
211 pub fn push_clip(&mut self, clip: RoundedRect) {
212 self.writer.write_payload(PushClipPayload { clip });
213 self.enter_scope();
214 }
215
216 pub fn push_geometry_clip(&mut self, geometry: Option<RenderDataResource>) {
217 let payload = PushGeometryClipPayload { geometry: self.resources.intern(geometry) };
218 self.writer.write_payload(payload);
219 self.enter_scope();
220 }
221
222 pub fn push_opacity(&mut self, opacity: f64) {
223 self.writer.write_payload(PushOpacityPayload { opacity });
224 self.enter_scope();
225 }
226
227 pub fn push_opacity_mask(&mut self, server_brush: Option<RenderDataResource>, bounds: Rect) {
228 let payload = PushOpacityMaskPayload { brush: self.resources.intern(server_brush), bounds };
229 self.writer.write_payload(payload);
230 self.enter_scope();
231 }
232
233 pub fn push_transform(&mut self, matrix: Matrix) {
234 self.writer.write_payload(PushTransformPayload { matrix });
235 self.enter_scope();
236 }
237
238 pub fn push_render_options(&mut self, options: RenderOptions) {
239 self.writer.write_payload(PushRenderOptionsPayload { options });
240 self.enter_scope();
241 }
242
243 pub fn push_text_options(&mut self, text_options: TextOptions) {
244 self.writer.write_payload(PushTextOptionsPayload { options: text_options });
245 self.enter_scope();
246 }
247
248 pub fn push_effect(&mut self, effect: Option<Arc<dyn crate::media::IImmutableEffect>>, bounds: Rect) {
249 let payload =
250 PushEffectPayload { effect: self.resources.intern(effect.map(RenderDataResource::Effect)), bounds };
251 self.writer.write_payload(payload);
252 self.enter_scope();
253 }
254
255 pub fn pop(&mut self) {
256 self.writer.write_opcode(RenderDataOpcode::Pop);
257 self.depth -= 1;
258 }
259
260 pub fn serialize_to(&self, writer: &mut BatchStreamWriter<'_>) {
264 writer.write(self.max_depth);
265 writer.write(self.resources.count() as i32);
266 for resource in self.resources.iter() {
267 match resource {
268 RenderDataResource::ClientPen(_) | RenderDataResource::NotSent => writer.write(TAG_NOT_SENT),
269 RenderDataResource::Brush(v) => {
272 writer.write(TAG_BRUSH);
273 let shared = crate::media::shared_brush_of(&**v)
274 .unwrap_or_else(|| panic!("The brush is not compatible with composition"));
275 writer.write_object(BatchObject::value(shared));
276 }
277 RenderDataResource::Pen(v) => {
278 writer.write(TAG_PEN);
279 let shared = crate::media::shared_pen_of(&**v)
280 .unwrap_or_else(|| panic!("The pen is not compatible with composition"));
281 writer.write_object(BatchObject::value(shared));
282 }
283 RenderDataResource::GeometryImpl(v) => {
284 writer.write(TAG_GEOMETRY_IMPL);
285 writer.write_object(BatchObject::value(v.clone()));
286 }
287 RenderDataResource::Geometry(_) => panic!("a geometry of render data is not sent by value"),
291 RenderDataResource::GlyphRun(v) => {
292 writer.write(TAG_GLYPH_RUN);
293 writer.write_object(BatchObject::value(v.clone()));
294 }
295 RenderDataResource::Bitmap(v) => {
296 writer.write(TAG_BITMAP);
297 writer.write_object(BatchObject::value(v.clone()));
298 }
299 RenderDataResource::CustomDrawOperation(v) => {
300 writer.write(TAG_CUSTOM);
301 writer.write_object(BatchObject::value(v.clone()));
302 }
303 RenderDataResource::Effect(v) => {
304 writer.write(TAG_EFFECT);
305 writer.write_object(BatchObject::value(v.clone()));
306 }
307 RenderDataResource::ServerBrush { server, .. } => {
308 writer.write(TAG_SERVER_BRUSH);
309 writer.write_server_object(Some(*server));
310 }
311 RenderDataResource::ServerPen { server, .. } => {
312 writer.write(TAG_SERVER_PEN);
313 writer.write_server_object(Some(*server));
314 }
315 RenderDataResource::ServerGeometry { server, .. } => {
316 writer.write(TAG_SERVER_GEOMETRY);
317 writer.write_server_object(Some(*server));
318 }
319 }
320 }
321 let opcodes = self.writer.written();
322 writer.write(opcodes.len() as i32);
323 writer.write_bytes(opcodes);
324 }
325
326 pub fn deserialize_from(
329 &mut self,
330 reader: &mut BatchStreamReader<'_>,
331 resolve: &dyn Fn(ServerObjectId) -> Option<Rc<dyn IServerObject>>,
332 ) {
333 fn value<T: 'static>(reader: &mut BatchStreamReader<'_>) -> T {
334 match reader.read_value::<T>() {
335 Some(value) => value,
336 None => panic!("a render data resource is missing from the batch"),
337 }
338 }
339 fn server_object(
340 reader: &mut BatchStreamReader<'_>,
341 resolve: &dyn Fn(ServerObjectId) -> Option<Rc<dyn IServerObject>>,
342 ) -> Rc<dyn IServerObject> {
343 match reader.read_server_object().and_then(resolve) {
344 Some(object) => object,
345 None => panic!("render data refers to a server object that does not exist"),
346 }
347 }
348
349 self.max_depth = reader.read::<i32>();
350 let resource_count = reader.read::<i32>();
351 for _ in 0..resource_count {
352 let resource = match reader.read::<u8>() {
353 TAG_NOT_SENT => RenderDataResource::NotSent,
354 TAG_BRUSH => RenderDataResource::Brush(Rc::new(value::<crate::media::SharedBrush>(reader))),
355 TAG_PEN => RenderDataResource::Pen(Rc::new(value::<crate::media::SharedPen>(reader))),
356 TAG_GEOMETRY_IMPL => RenderDataResource::GeometryImpl(value(reader)),
357 TAG_GLYPH_RUN => RenderDataResource::GlyphRun(value(reader)),
358 TAG_BITMAP => RenderDataResource::Bitmap(value(reader)),
359 TAG_CUSTOM => RenderDataResource::CustomDrawOperation(value(reader)),
360 TAG_EFFECT => RenderDataResource::Effect(value(reader)),
361 TAG_SERVER_BRUSH => match server_object(reader, resolve).as_brush() {
362 Some(brush) => RenderDataResource::Brush(brush),
363 None => panic!("the server object referenced by render data is not a brush"),
364 },
365 TAG_SERVER_PEN => match server_object(reader, resolve).as_pen() {
366 Some(pen) => RenderDataResource::Pen(pen),
367 None => panic!("the server object referenced by render data is not a pen"),
368 },
369 TAG_SERVER_GEOMETRY => match server_object(reader, resolve).as_render_data_geometry() {
370 Some(geometry) => RenderDataResource::Geometry(geometry),
371 None => panic!("the server object referenced by render data is not a geometry"),
372 },
373 _ => panic!("unknown render data resource tag"),
374 };
375 self.resources.append_deserialized(resource);
376 }
377 let byte_count = reader.read::<i32>();
378 if byte_count > 0 {
379 reader.read_bytes(self.writer.reserve(byte_count as usize));
380 }
381 }
382
383 pub fn visit<V: IRenderDataVisitor>(&self, visitor: &mut V) {
385 let mut scopes: Vec<V::Scope> = Vec::with_capacity(self.max_depth.max(0) as usize);
386 self.visit_with_scopes(visitor, &mut scopes);
387 }
388
389 pub fn visit_with_scopes<V: IRenderDataVisitor>(&self, visitor: &mut V, scopes: &mut Vec<V::Scope>) {
393 let resources = &self.resources;
394 let mut reader = RenderDataReader::new(self.writer.written());
395 while !visitor.stop_visiting() && !reader.is_at_end() {
396 match reader.peek::<RenderDataOpcode>() {
397 RenderDataOpcode::DrawLine => {
398 let p = reader.read_payload::<DrawLinePayload>();
399 visitor.on_draw_line(resources.pen(p.server_pen), resources.pen(p.client_pen), p.p1, p.p2);
400 }
401 RenderDataOpcode::DrawRectangle => {
402 let p = reader.read_payload::<DrawRectanglePayload>();
403 let shadows = Self::read_box_shadows(&mut reader, p.box_shadow_count);
404 visitor.on_draw_rectangle(
405 resources.brush(p.server_brush),
406 resources.pen(p.server_pen),
407 resources.pen(p.client_pen),
408 p.rect,
409 &shadows,
410 );
411 }
412 RenderDataOpcode::DrawEllipse => {
413 let p = reader.read_payload::<DrawEllipsePayload>();
414 visitor.on_draw_ellipse(
415 resources.brush(p.server_brush),
416 resources.pen(p.server_pen),
417 resources.pen(p.client_pen),
418 p.rect,
419 );
420 }
421 RenderDataOpcode::DrawGeometry => {
422 let p = reader.read_payload::<DrawGeometryPayload>();
423 visitor.on_draw_geometry(
424 resources.brush(p.server_brush),
425 resources.pen(p.server_pen),
426 resources.pen(p.client_pen),
427 resources.geometry_impl(p.geometry).as_ref(),
428 );
429 }
430 RenderDataOpcode::DrawGlyphRun => {
431 let p = reader.read_payload::<DrawGlyphRunPayload>();
432 visitor.on_draw_glyph_run(resources.brush(p.server_brush), resources.glyph_run(p.glyph_run));
433 }
434 RenderDataOpcode::DrawBitmap => {
435 let p = reader.read_payload::<DrawBitmapPayload>();
436 visitor.on_draw_bitmap(resources.bitmap(p.bitmap).as_ref(), p.opacity, p.source_rect, p.dest_rect);
437 }
438 RenderDataOpcode::DrawCustom => {
439 let p = reader.read_payload::<DrawCustomPayload>();
440 visitor.on_draw_custom(resources.custom_draw_operation(p.operation));
441 }
442 RenderDataOpcode::PushClip => {
443 let p = reader.read_payload::<PushClipPayload>();
444 scopes.push(visitor.on_push_clip(p.clip));
445 }
446 RenderDataOpcode::PushGeometryClip => {
447 let p = reader.read_payload::<PushGeometryClipPayload>();
448 scopes.push(visitor.on_push_geometry_clip(resources.geometry_impl(p.geometry).as_ref()));
449 }
450 RenderDataOpcode::PushOpacity => {
451 let p = reader.read_payload::<PushOpacityPayload>();
452 scopes.push(visitor.on_push_opacity(p.opacity));
453 }
454 RenderDataOpcode::PushOpacityMask => {
455 let p = reader.read_payload::<PushOpacityMaskPayload>();
456 scopes.push(visitor.on_push_opacity_mask(resources.brush(p.brush), p.bounds));
457 }
458 RenderDataOpcode::PushTransform => {
459 let p = reader.read_payload::<PushTransformPayload>();
460 scopes.push(visitor.on_push_transform(p.matrix));
461 }
462 RenderDataOpcode::PushRenderOptions => {
463 let p = reader.read_payload::<PushRenderOptionsPayload>();
464 scopes.push(visitor.on_push_render_options(p.options));
465 }
466 RenderDataOpcode::PushTextOptions => {
467 let p = reader.read_payload::<PushTextOptionsPayload>();
468 scopes.push(visitor.on_push_text_options(p.options));
469 }
470 RenderDataOpcode::PushEffect => {
471 let p = reader.read_payload::<PushEffectPayload>();
472 scopes.push(visitor.on_push_effect(resources.effect(p.effect), p.bounds));
473 }
474 RenderDataOpcode::Pop => {
475 reader.read::<RenderDataOpcode>();
476 let scope = scopes.pop().expect("a pop without a matching push in render data");
477 visitor.on_pop(scope);
478 }
479 RenderDataOpcode::Invalid => panic!("render data holds an invalid opcode"),
480 }
481 }
482 scopes.clear();
483 }
484
485 fn read_box_shadows(reader: &mut RenderDataReader<'_>, count: i32) -> BoxShadows {
486 if count == 0 {
487 return BoxShadows::default();
488 }
489
490 let first = reader.read::<BoxShadow>();
491 if count == 1 {
492 return BoxShadows::new(first);
493 }
494
495 let rest: Vec<BoxShadow> = (1..count).map(|_| reader.read::<BoxShadow>()).collect();
496 BoxShadows::with_rest(first, &rest)
497 }
498
499 pub fn dispose(&mut self) {
501 self.writer.dispose();
502 self.resources.dispose();
503 }
504}