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