1use bitflags::bitflags;
8use crate::Matrix;
9use crate::Vector;
10use crate::rendering::composition::CompositionBitmapInterpolationMode;
11use crate::rendering::composition::CompositionStretch;
12use crate::rendering::composition::ICompositionObject;
13use crate::rendering::composition::animations::AnimationInstanceFactory;
14use crate::rendering::composition::animations::ICompositionAnimation;
15use crate::rendering::composition::expressions::ExpressionVariant;
16use crate::rendering::composition::server::AsServerRenderResource;
17use crate::rendering::composition::server::CompositionProperty;
18use crate::rendering::composition::server::CompositionPropertyOf;
19use crate::rendering::composition::server::IServerObject;
20use crate::rendering::composition::server::ServerPropertyValue;
21use crate::rendering::composition::server::ServerValueChange;
22use crate::rendering::composition::server::props_of;
23use crate::rendering::composition::server::read_server_object;
24use crate::rendering::composition::transport::BatchStreamReader;
25use crate::rendering::composition::transport::BatchStreamWriter;
26use crate::rendering::composition::transport::BatchValue;
27use crate::rendering::composition::transport::BatchValueReader;
28use std::any::Any;
29use std::any::TypeId;
30use std::cell::Cell;
31use std::cell::RefCell;
32use std::rc::Rc;
33use std::sync::OnceLock;
34use std::time::Duration;
35use super::CompositionBrushHooks;
36use super::CompositionBrushProps;
37use super::ServerCompositionBrushHooks;
38use super::ServerCompositionBrushProps;
39
40bitflags! {
41 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
43 pub struct CompositionSurfaceBrushChangedFields: u32 {
44 const SURFACE = 1;
45 const STRETCH = 2;
46 const HORIZONTAL_ALIGNMENT_RATIO = 4;
47 const HORIZONTAL_ALIGNMENT_RATIO_ANIMATED = 8;
48 const VERTICAL_ALIGNMENT_RATIO = 16;
49 const VERTICAL_ALIGNMENT_RATIO_ANIMATED = 32;
50 const BITMAP_INTERPOLATION_MODE = 64;
51 const ANCHOR_POINT = 128;
52 const ANCHOR_POINT_ANIMATED = 256;
53 const CENTER_POINT = 512;
54 const CENTER_POINT_ANIMATED = 1024;
55 const OFFSET = 2048;
56 const OFFSET_ANIMATED = 4096;
57 const ROTATION_ANGLE = 8192;
58 const ROTATION_ANGLE_ANIMATED = 16384;
59 const SCALE = 32768;
60 const SCALE_ANIMATED = 65536;
61 const TRANSFORM_MATRIX = 131072;
62 const TRANSFORM_MATRIX_ANIMATED = 262144;
63 const SNAP_TO_PIXELS = 524288;
64 }
65}
66
67impl BatchValue for CompositionSurfaceBrushChangedFields {
68 #[inline]
69 fn write_to(&self, out: &mut Vec<u8>) {
70 self.bits().write_to(out);
71 }
72
73 #[inline]
74 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
75 CompositionSurfaceBrushChangedFields::from_bits_retain(u32::read_from(input))
76 }
77}
78
79pub trait CompositionSurfaceBrushHooks: CompositionBrushHooks {
82 fn initialize_defaults_extra(&self) {}
83
84 fn validate_surface_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
85 fn on_surface_changed(&self) {}
86 fn on_surface_changing(&self) {}
87
88 fn validate_stretch_change(&self, _old_value: CompositionStretch, _new_value: CompositionStretch) {}
89 fn on_stretch_changed(&self) {}
90 fn on_stretch_changing(&self) {}
91
92 fn validate_horizontal_alignment_ratio_change(&self, _old_value: f32, _new_value: f32) {}
93 fn on_horizontal_alignment_ratio_changed(&self) {}
94 fn on_horizontal_alignment_ratio_changing(&self) {}
95
96 fn validate_vertical_alignment_ratio_change(&self, _old_value: f32, _new_value: f32) {}
97 fn on_vertical_alignment_ratio_changed(&self) {}
98 fn on_vertical_alignment_ratio_changing(&self) {}
99
100 fn validate_bitmap_interpolation_mode_change(&self, _old_value: CompositionBitmapInterpolationMode, _new_value: CompositionBitmapInterpolationMode) {}
101 fn on_bitmap_interpolation_mode_changed(&self) {}
102 fn on_bitmap_interpolation_mode_changing(&self) {}
103
104 fn validate_anchor_point_change(&self, _old_value: Vector, _new_value: Vector) {}
105 fn on_anchor_point_changed(&self) {}
106 fn on_anchor_point_changing(&self) {}
107
108 fn validate_center_point_change(&self, _old_value: Vector, _new_value: Vector) {}
109 fn on_center_point_changed(&self) {}
110 fn on_center_point_changing(&self) {}
111
112 fn validate_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
113 fn on_offset_changed(&self) {}
114 fn on_offset_changing(&self) {}
115
116 fn validate_rotation_angle_change(&self, _old_value: f32, _new_value: f32) {}
117 fn on_rotation_angle_changed(&self) {}
118 fn on_rotation_angle_changing(&self) {}
119
120 fn validate_scale_change(&self, _old_value: Vector, _new_value: Vector) {}
121 fn on_scale_changed(&self) {}
122 fn on_scale_changing(&self) {}
123
124 fn validate_transform_matrix_change(&self, _old_value: Matrix, _new_value: Matrix) {}
125 fn on_transform_matrix_changed(&self) {}
126 fn on_transform_matrix_changing(&self) {}
127
128 fn validate_snap_to_pixels_change(&self, _old_value: bool, _new_value: bool) {}
129 fn on_snap_to_pixels_changed(&self) {}
130 fn on_snap_to_pixels_changing(&self) {}
131}
132
133pub struct CompositionSurfaceBrushProps {
135 base: CompositionBrushProps,
136 changed_fields_of_composition_surface_brush: Cell<CompositionSurfaceBrushChangedFields>,
137 surface: RefCell<Option<Rc<dyn ICompositionObject>>>,
138 stretch: Cell<CompositionStretch>,
139 horizontal_alignment_ratio: Cell<f32>,
140 vertical_alignment_ratio: Cell<f32>,
141 bitmap_interpolation_mode: Cell<CompositionBitmapInterpolationMode>,
142 anchor_point: Cell<Vector>,
143 center_point: Cell<Vector>,
144 offset: Cell<Vector>,
145 rotation_angle: Cell<f32>,
146 scale: Cell<Vector>,
147 transform_matrix: Cell<Matrix>,
148 snap_to_pixels: Cell<bool>,
149}
150
151impl Default for CompositionSurfaceBrushProps {
152 fn default() -> Self {
153 Self::new()
154 }
155}
156
157impl CompositionSurfaceBrushProps {
158 pub fn new() -> Self {
162 Self {
163 base: CompositionBrushProps::new(),
164 changed_fields_of_composition_surface_brush: Cell::new(CompositionSurfaceBrushChangedFields::empty()),
165 surface: RefCell::new(None),
166 stretch: Cell::new(Default::default()),
167 horizontal_alignment_ratio: Cell::new(Default::default()),
168 vertical_alignment_ratio: Cell::new(Default::default()),
169 bitmap_interpolation_mode: Cell::new(Default::default()),
170 anchor_point: Cell::new(Default::default()),
171 center_point: Cell::new(Default::default()),
172 offset: Cell::new(Default::default()),
173 rotation_angle: Cell::new(Default::default()),
174 scale: Cell::new(Default::default()),
175 transform_matrix: Cell::new(Default::default()),
176 snap_to_pixels: Cell::new(Default::default()),
177 }
178 }
179
180 pub fn base(&self) -> &CompositionBrushProps {
182 &self.base
183 }
184
185 pub fn initialize_defaults(&self, host: &dyn CompositionSurfaceBrushHooks) {
188 self.base.initialize_defaults(host);
189 self.initialize_own_defaults(host);
190 }
191
192 pub fn initialize_own_defaults(&self, host: &dyn CompositionSurfaceBrushHooks) {
194 CompositionSurfaceBrushHooks::initialize_defaults_extra(host);
195 self.set_stretch(host, CompositionStretch::Fill);
196 self.set_horizontal_alignment_ratio(host, 0.5);
197 self.set_vertical_alignment_ratio(host, 0.5);
198 self.set_bitmap_interpolation_mode(host, CompositionBitmapInterpolationMode::Linear);
199 self.set_scale(host, Vector::new(1.0, 1.0));
200 self.set_transform_matrix(host, Matrix::IDENTITY);
201 }
202
203 pub fn surface(&self) -> Option<Rc<dyn ICompositionObject>> {
205 self.surface.borrow().clone()
206 }
207
208 pub fn set_surface(&self, host: &dyn CompositionSurfaceBrushHooks, value: Option<Rc<dyn ICompositionObject>>) {
210 let mut changed = false;
211 let old_value = self.surface.borrow().clone();
212 if old_value.differs(&value) {
213 CompositionSurfaceBrushHooks::validate_surface_change(host, &old_value, &value);
214 CompositionSurfaceBrushHooks::on_surface_changing(host);
215 changed = true;
216 *self.surface.borrow_mut() = value.clone();
218 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SURFACE);
220 host.register_for_serialization();
221 }
222 *self.surface.borrow_mut() = value;
223 if changed {
224 CompositionSurfaceBrushHooks::on_surface_changed(host);
225 }
226 }
227
228 pub fn stretch(&self) -> CompositionStretch {
230 self.stretch.get()
231 }
232
233 pub fn set_stretch(&self, host: &dyn CompositionSurfaceBrushHooks, value: CompositionStretch) {
235 let mut changed = false;
236 let old_value = self.stretch.get();
237 if old_value.differs(&value) {
238 CompositionSurfaceBrushHooks::validate_stretch_change(host, old_value, value);
239 CompositionSurfaceBrushHooks::on_stretch_changing(host);
240 changed = true;
241 self.stretch.set(value);
243 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::STRETCH);
245 host.register_for_serialization();
246 }
247 self.stretch.set(value);
248 if changed {
249 CompositionSurfaceBrushHooks::on_stretch_changed(host);
250 }
251 }
252
253 pub fn horizontal_alignment_ratio(&self) -> f32 {
255 self.horizontal_alignment_ratio.get()
256 }
257
258 pub fn set_horizontal_alignment_ratio(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
260 let mut changed = false;
261 let old_value = self.horizontal_alignment_ratio.get();
262 if old_value.differs(&value) {
263 CompositionSurfaceBrushHooks::validate_horizontal_alignment_ratio_change(host, old_value, value);
264 CompositionSurfaceBrushHooks::on_horizontal_alignment_ratio_changing(host);
265 changed = true;
266 self.horizontal_alignment_ratio.set(value);
268 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO);
270 host.register_for_serialization();
271 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base());
273 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
274 if let Some(animation) = host.implicit_animation("HorizontalAlignmentRatio") {
276 if let Some(a) = animation.as_composition_animation() {
278 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
279 host.pending_animations().set(
280 ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base(),
281 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
282 );
283 }
284 host.start_animation_group(&animation, "HorizontalAlignmentRatio", ExpressionVariant::create(value));
286 }
287 }
288 self.horizontal_alignment_ratio.set(value);
289 if changed {
290 CompositionSurfaceBrushHooks::on_horizontal_alignment_ratio_changed(host);
291 }
292 }
293
294 pub fn vertical_alignment_ratio(&self) -> f32 {
296 self.vertical_alignment_ratio.get()
297 }
298
299 pub fn set_vertical_alignment_ratio(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
301 let mut changed = false;
302 let old_value = self.vertical_alignment_ratio.get();
303 if old_value.differs(&value) {
304 CompositionSurfaceBrushHooks::validate_vertical_alignment_ratio_change(host, old_value, value);
305 CompositionSurfaceBrushHooks::on_vertical_alignment_ratio_changing(host);
306 changed = true;
307 self.vertical_alignment_ratio.set(value);
309 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO);
311 host.register_for_serialization();
312 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base());
314 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
315 if let Some(animation) = host.implicit_animation("VerticalAlignmentRatio") {
317 if let Some(a) = animation.as_composition_animation() {
319 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
320 host.pending_animations().set(
321 ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base(),
322 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
323 );
324 }
325 host.start_animation_group(&animation, "VerticalAlignmentRatio", ExpressionVariant::create(value));
327 }
328 }
329 self.vertical_alignment_ratio.set(value);
330 if changed {
331 CompositionSurfaceBrushHooks::on_vertical_alignment_ratio_changed(host);
332 }
333 }
334
335 pub fn bitmap_interpolation_mode(&self) -> CompositionBitmapInterpolationMode {
337 self.bitmap_interpolation_mode.get()
338 }
339
340 pub fn set_bitmap_interpolation_mode(&self, host: &dyn CompositionSurfaceBrushHooks, value: CompositionBitmapInterpolationMode) {
342 let mut changed = false;
343 let old_value = self.bitmap_interpolation_mode.get();
344 if old_value.differs(&value) {
345 CompositionSurfaceBrushHooks::validate_bitmap_interpolation_mode_change(host, old_value, value);
346 CompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changing(host);
347 changed = true;
348 self.bitmap_interpolation_mode.set(value);
350 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE);
352 host.register_for_serialization();
353 }
354 self.bitmap_interpolation_mode.set(value);
355 if changed {
356 CompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changed(host);
357 }
358 }
359
360 pub fn anchor_point(&self) -> Vector {
362 self.anchor_point.get()
363 }
364
365 pub fn set_anchor_point(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
367 let mut changed = false;
368 let old_value = self.anchor_point.get();
369 if old_value.differs(&value) {
370 CompositionSurfaceBrushHooks::validate_anchor_point_change(host, old_value, value);
371 CompositionSurfaceBrushHooks::on_anchor_point_changing(host);
372 changed = true;
373 self.anchor_point.set(value);
375 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ANCHOR_POINT);
377 host.register_for_serialization();
378 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base());
380 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED);
381 if let Some(animation) = host.implicit_animation("AnchorPoint") {
383 if let Some(a) = animation.as_composition_animation() {
385 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED);
386 host.pending_animations().set(
387 ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base(),
388 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
389 );
390 }
391 host.start_animation_group(&animation, "AnchorPoint", ExpressionVariant::create(value));
393 }
394 }
395 self.anchor_point.set(value);
396 if changed {
397 CompositionSurfaceBrushHooks::on_anchor_point_changed(host);
398 }
399 }
400
401 pub fn center_point(&self) -> Vector {
403 self.center_point.get()
404 }
405
406 pub fn set_center_point(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
408 let mut changed = false;
409 let old_value = self.center_point.get();
410 if old_value.differs(&value) {
411 CompositionSurfaceBrushHooks::validate_center_point_change(host, old_value, value);
412 CompositionSurfaceBrushHooks::on_center_point_changing(host);
413 changed = true;
414 self.center_point.set(value);
416 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT);
418 host.register_for_serialization();
419 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base());
421 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
422 if let Some(animation) = host.implicit_animation("CenterPoint") {
424 if let Some(a) = animation.as_composition_animation() {
426 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
427 host.pending_animations().set(
428 ServerCompositionSurfaceBrushProps::id_of_center_point_property().base(),
429 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
430 );
431 }
432 host.start_animation_group(&animation, "CenterPoint", ExpressionVariant::create(value));
434 }
435 }
436 self.center_point.set(value);
437 if changed {
438 CompositionSurfaceBrushHooks::on_center_point_changed(host);
439 }
440 }
441
442 pub fn offset(&self) -> Vector {
444 self.offset.get()
445 }
446
447 pub fn set_offset(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
449 let mut changed = false;
450 let old_value = self.offset.get();
451 if old_value.differs(&value) {
452 CompositionSurfaceBrushHooks::validate_offset_change(host, old_value, value);
453 CompositionSurfaceBrushHooks::on_offset_changing(host);
454 changed = true;
455 self.offset.set(value);
457 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET);
459 host.register_for_serialization();
460 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_offset_property().base());
462 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
463 if let Some(animation) = host.implicit_animation("Offset") {
465 if let Some(a) = animation.as_composition_animation() {
467 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
468 host.pending_animations().set(
469 ServerCompositionSurfaceBrushProps::id_of_offset_property().base(),
470 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
471 );
472 }
473 host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
475 }
476 }
477 self.offset.set(value);
478 if changed {
479 CompositionSurfaceBrushHooks::on_offset_changed(host);
480 }
481 }
482
483 pub fn rotation_angle(&self) -> f32 {
485 self.rotation_angle.get()
486 }
487
488 pub fn set_rotation_angle(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
490 let mut changed = false;
491 let old_value = self.rotation_angle.get();
492 if old_value.differs(&value) {
493 CompositionSurfaceBrushHooks::validate_rotation_angle_change(host, old_value, value);
494 CompositionSurfaceBrushHooks::on_rotation_angle_changing(host);
495 changed = true;
496 self.rotation_angle.set(value);
498 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE);
500 host.register_for_serialization();
501 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base());
503 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
504 if let Some(animation) = host.implicit_animation("RotationAngle") {
506 if let Some(a) = animation.as_composition_animation() {
508 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
509 host.pending_animations().set(
510 ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base(),
511 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
512 );
513 }
514 host.start_animation_group(&animation, "RotationAngle", ExpressionVariant::create(value));
516 }
517 }
518 self.rotation_angle.set(value);
519 if changed {
520 CompositionSurfaceBrushHooks::on_rotation_angle_changed(host);
521 }
522 }
523
524 pub fn scale(&self) -> Vector {
526 self.scale.get()
527 }
528
529 pub fn set_scale(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
531 let mut changed = false;
532 let old_value = self.scale.get();
533 if old_value.differs(&value) {
534 CompositionSurfaceBrushHooks::validate_scale_change(host, old_value, value);
535 CompositionSurfaceBrushHooks::on_scale_changing(host);
536 changed = true;
537 self.scale.set(value);
539 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SCALE);
541 host.register_for_serialization();
542 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_scale_property().base());
544 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::SCALE_ANIMATED);
545 if let Some(animation) = host.implicit_animation("Scale") {
547 if let Some(a) = animation.as_composition_animation() {
549 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SCALE_ANIMATED);
550 host.pending_animations().set(
551 ServerCompositionSurfaceBrushProps::id_of_scale_property().base(),
552 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
553 );
554 }
555 host.start_animation_group(&animation, "Scale", ExpressionVariant::create(value));
557 }
558 }
559 self.scale.set(value);
560 if changed {
561 CompositionSurfaceBrushHooks::on_scale_changed(host);
562 }
563 }
564
565 pub fn transform_matrix(&self) -> Matrix {
567 self.transform_matrix.get()
568 }
569
570 pub fn set_transform_matrix(&self, host: &dyn CompositionSurfaceBrushHooks, value: Matrix) {
572 let mut changed = false;
573 let old_value = self.transform_matrix.get();
574 if old_value.differs(&value) {
575 CompositionSurfaceBrushHooks::validate_transform_matrix_change(host, old_value, value);
576 CompositionSurfaceBrushHooks::on_transform_matrix_changing(host);
577 changed = true;
578 self.transform_matrix.set(value);
580 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX);
582 host.register_for_serialization();
583 host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base());
585 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
586 if let Some(animation) = host.implicit_animation("TransformMatrix") {
588 if let Some(a) = animation.as_composition_animation() {
590 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
591 host.pending_animations().set(
592 ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base(),
593 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
594 );
595 }
596 host.start_animation_group(&animation, "TransformMatrix", ExpressionVariant::create(value));
598 }
599 }
600 self.transform_matrix.set(value);
601 if changed {
602 CompositionSurfaceBrushHooks::on_transform_matrix_changed(host);
603 }
604 }
605
606 pub fn snap_to_pixels(&self) -> bool {
608 self.snap_to_pixels.get()
609 }
610
611 pub fn set_snap_to_pixels(&self, host: &dyn CompositionSurfaceBrushHooks, value: bool) {
613 let mut changed = false;
614 let old_value = self.snap_to_pixels.get();
615 if old_value.differs(&value) {
616 CompositionSurfaceBrushHooks::validate_snap_to_pixels_change(host, old_value, value);
617 CompositionSurfaceBrushHooks::on_snap_to_pixels_changing(host);
618 changed = true;
619 self.snap_to_pixels.set(value);
621 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS);
623 host.register_for_serialization();
624 }
625 self.snap_to_pixels.set(value);
626 if changed {
627 CompositionSurfaceBrushHooks::on_snap_to_pixels_changed(host);
628 }
629 }
630
631 pub fn start_animation(
635 &self,
636 host: &dyn CompositionSurfaceBrushHooks,
637 property_name: &str,
638 animation: &dyn ICompositionAnimation,
639 final_value: Option<ExpressionVariant>,
640 ) -> bool {
641 if property_name == "HorizontalAlignmentRatio" {
642 let server = animation.create_instance(host.server(), final_value);
643 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base(), server);
644 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
645 host.register_for_serialization();
646 return true;
647 }
648 if property_name == "VerticalAlignmentRatio" {
649 let server = animation.create_instance(host.server(), final_value);
650 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base(), server);
651 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
652 host.register_for_serialization();
653 return true;
654 }
655 if property_name == "AnchorPoint" {
656 let server = animation.create_instance(host.server(), final_value);
657 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base(), server);
658 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED);
659 host.register_for_serialization();
660 return true;
661 }
662 if property_name == "CenterPoint" {
663 let server = animation.create_instance(host.server(), final_value);
664 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base(), server);
665 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
666 host.register_for_serialization();
667 return true;
668 }
669 if property_name == "Offset" {
670 let server = animation.create_instance(host.server(), final_value);
671 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_offset_property().base(), server);
672 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
673 host.register_for_serialization();
674 return true;
675 }
676 if property_name == "RotationAngle" {
677 let server = animation.create_instance(host.server(), final_value);
678 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base(), server);
679 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
680 host.register_for_serialization();
681 return true;
682 }
683 if property_name == "Scale" {
684 let server = animation.create_instance(host.server(), final_value);
685 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_scale_property().base(), server);
686 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SCALE_ANIMATED);
687 host.register_for_serialization();
688 return true;
689 }
690 if property_name == "TransformMatrix" {
691 let server = animation.create_instance(host.server(), final_value);
692 host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base(), server);
693 self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
694 host.register_for_serialization();
695 return true;
696 }
697 self.base.start_animation(host, property_name, animation, final_value)
698 }
699
700 pub fn serialize_changes_core(&self, host: &dyn CompositionSurfaceBrushHooks, writer: &mut BatchStreamWriter<'_>) {
703 self.base.serialize_changes_core(host, writer);
704 let changed = self.changed_fields_of_composition_surface_brush.get();
705 writer.write(changed);
706 if changed.contains(CompositionSurfaceBrushChangedFields::SURFACE) {
707 writer.write_server_object(self.surface.borrow().clone().map(|o| o.server()));
708 }
709 if changed.contains(CompositionSurfaceBrushChangedFields::STRETCH) {
710 writer.write(self.stretch.get());
711 }
712 if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED) {
713 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base()));
714 } else if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO) {
715 writer.write(self.horizontal_alignment_ratio.get());
716 }
717 if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED) {
718 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base()));
719 } else if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO) {
720 writer.write(self.vertical_alignment_ratio.get());
721 }
722 if changed.contains(CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE) {
723 writer.write(self.bitmap_interpolation_mode.get());
724 }
725 if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED) {
726 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base()));
727 } else if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT) {
728 writer.write(self.anchor_point.get());
729 }
730 if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED) {
731 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base()));
732 } else if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT) {
733 writer.write(self.center_point.get());
734 }
735 if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED) {
736 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_offset_property().base()));
737 } else if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET) {
738 writer.write(self.offset.get());
739 }
740 if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED) {
741 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base()));
742 } else if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE) {
743 writer.write(self.rotation_angle.get());
744 }
745 if changed.contains(CompositionSurfaceBrushChangedFields::SCALE_ANIMATED) {
746 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_scale_property().base()));
747 } else if changed.contains(CompositionSurfaceBrushChangedFields::SCALE) {
748 writer.write(self.scale.get());
749 }
750 if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED) {
751 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base()));
752 } else if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX) {
753 writer.write(self.transform_matrix.get());
754 }
755 if changed.contains(CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS) {
756 writer.write(self.snap_to_pixels.get());
757 }
758 self.changed_fields_of_composition_surface_brush.set(CompositionSurfaceBrushChangedFields::empty());
759 }
760}
761
762pub trait ServerCompositionSurfaceBrushHooks: ServerCompositionBrushHooks {
765 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
766 fn on_fields_deserialized(&self, _changed: CompositionSurfaceBrushChangedFields) {}
767
768 fn on_surface_changed(&self) {}
769 fn on_surface_changing(&self) {}
770
771 fn on_stretch_changed(&self) {}
772 fn on_stretch_changing(&self) {}
773
774 fn on_bitmap_interpolation_mode_changed(&self) {}
775 fn on_bitmap_interpolation_mode_changing(&self) {}
776
777 fn on_snap_to_pixels_changed(&self) {}
778 fn on_snap_to_pixels_changing(&self) {}
779}
780
781pub struct ServerCompositionSurfaceBrushProps {
783 base: ServerCompositionBrushProps,
784 surface: RefCell<Option<Rc<dyn IServerObject>>>,
785 stretch: Cell<CompositionStretch>,
786 horizontal_alignment_ratio: Cell<f32>,
787 vertical_alignment_ratio: Cell<f32>,
788 bitmap_interpolation_mode: Cell<CompositionBitmapInterpolationMode>,
789 anchor_point: Cell<Vector>,
790 center_point: Cell<Vector>,
791 offset: Cell<Vector>,
792 rotation_angle: Cell<f32>,
793 scale: Cell<Vector>,
794 transform_matrix: Cell<Matrix>,
795 snap_to_pixels: Cell<bool>,
796}
797
798impl Default for ServerCompositionSurfaceBrushProps {
799 fn default() -> Self {
800 Self::new()
801 }
802}
803
804impl ServerCompositionSurfaceBrushProps {
805 pub fn new() -> Self {
808 Self {
809 base: ServerCompositionBrushProps::new(),
810 surface: RefCell::new(None),
811 stretch: Cell::new(Default::default()),
812 horizontal_alignment_ratio: Cell::new(Default::default()),
813 vertical_alignment_ratio: Cell::new(Default::default()),
814 bitmap_interpolation_mode: Cell::new(Default::default()),
815 anchor_point: Cell::new(Default::default()),
816 center_point: Cell::new(Default::default()),
817 offset: Cell::new(Default::default()),
818 rotation_angle: Cell::new(Default::default()),
819 scale: Cell::new(Default::default()),
820 transform_matrix: Cell::new(Default::default()),
821 snap_to_pixels: Cell::new(Default::default()),
822 }
823 }
824
825 pub fn base(&self) -> &ServerCompositionBrushProps {
827 &self.base
828 }
829
830 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
833 if type_id == TypeId::of::<Self>() {
834 return Some(self);
835 }
836 self.base.find_props(type_id)
837 }
838
839 pub fn id_of_surface_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
841 static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
842 PROPERTY.get_or_init(|| {
843 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Option<Rc<dyn IServerObject>>>(
844 "Surface",
845 "ServerCompositionSurfaceBrush",
846 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).surface.borrow().clone(),
847 |obj, v| *props_of::<ServerCompositionSurfaceBrushProps>(obj).surface.borrow_mut() = v,
848 None,
849 None,
850 )
851 })
852 }
853
854 pub fn surface(&self) -> Option<Rc<dyn IServerObject>> {
856 self.surface.borrow().clone()
857 }
858
859 pub fn set_surface(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Option<Rc<dyn IServerObject>>) {
860 let old_value = self.surface.borrow().clone();
861 let mut changed = false;
862 if old_value.differs(&value) {
863 ServerCompositionSurfaceBrushHooks::on_surface_changing(host);
864 changed = true;
865 }
866 host.set_value(
867 Self::id_of_surface_property().base(),
868 ServerValueChange {
869 equal: old_value.default_equals(&value),
870 old_resource: old_value.as_server_render_resource(),
871 new_resource: value.as_server_render_resource(),
872 assign: &mut || *self.surface.borrow_mut() = value.clone(),
873 },
874 );
875 if changed {
876 ServerCompositionSurfaceBrushHooks::on_surface_changed(host);
877 }
878 }
879
880 pub fn id_of_stretch_property() -> &'static CompositionPropertyOf<CompositionStretch> {
882 static PROPERTY: OnceLock<CompositionPropertyOf<CompositionStretch>> = OnceLock::new();
883 PROPERTY.get_or_init(|| {
884 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, CompositionStretch>(
885 "Stretch",
886 "ServerCompositionSurfaceBrush",
887 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).stretch.get(),
888 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).stretch.set(v),
889 None,
890 None,
891 )
892 })
893 }
894
895 pub fn stretch(&self) -> CompositionStretch {
897 self.stretch.get()
898 }
899
900 pub fn set_stretch(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: CompositionStretch) {
901 let old_value = self.stretch.get();
902 let mut changed = false;
903 if old_value.differs(&value) {
904 ServerCompositionSurfaceBrushHooks::on_stretch_changing(host);
905 changed = true;
906 }
907 host.set_value(
908 Self::id_of_stretch_property().base(),
909 ServerValueChange {
910 equal: old_value.default_equals(&value),
911 old_resource: None,
912 new_resource: None,
913 assign: &mut || self.stretch.set(value),
914 },
915 );
916 if changed {
917 ServerCompositionSurfaceBrushHooks::on_stretch_changed(host);
918 }
919 }
920
921 pub fn id_of_horizontal_alignment_ratio_property() -> &'static CompositionPropertyOf<f32> {
923 static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
924 PROPERTY.get_or_init(|| {
925 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, f32>(
926 "HorizontalAlignmentRatio",
927 "ServerCompositionSurfaceBrush",
928 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.get(),
929 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.set(v),
930 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.get())),
931 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.set(v.cast_or_default::<f32>())),
932 )
933 })
934 }
935
936 pub fn horizontal_alignment_ratio(&self) -> f32 {
938 self.horizontal_alignment_ratio.get()
939 }
940
941 pub fn set_horizontal_alignment_ratio(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: f32) {
942 self.horizontal_alignment_ratio.set(value);
943 host.remove_animation_for_property(Self::id_of_horizontal_alignment_ratio_property().base());
944 }
945
946 pub fn id_of_vertical_alignment_ratio_property() -> &'static CompositionPropertyOf<f32> {
948 static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
949 PROPERTY.get_or_init(|| {
950 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, f32>(
951 "VerticalAlignmentRatio",
952 "ServerCompositionSurfaceBrush",
953 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.get(),
954 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.set(v),
955 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.get())),
956 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.set(v.cast_or_default::<f32>())),
957 )
958 })
959 }
960
961 pub fn vertical_alignment_ratio(&self) -> f32 {
963 self.vertical_alignment_ratio.get()
964 }
965
966 pub fn set_vertical_alignment_ratio(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: f32) {
967 self.vertical_alignment_ratio.set(value);
968 host.remove_animation_for_property(Self::id_of_vertical_alignment_ratio_property().base());
969 }
970
971 pub fn id_of_bitmap_interpolation_mode_property() -> &'static CompositionPropertyOf<CompositionBitmapInterpolationMode> {
973 static PROPERTY: OnceLock<CompositionPropertyOf<CompositionBitmapInterpolationMode>> = OnceLock::new();
974 PROPERTY.get_or_init(|| {
975 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, CompositionBitmapInterpolationMode>(
976 "BitmapInterpolationMode",
977 "ServerCompositionSurfaceBrush",
978 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).bitmap_interpolation_mode.get(),
979 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).bitmap_interpolation_mode.set(v),
980 None,
981 None,
982 )
983 })
984 }
985
986 pub fn bitmap_interpolation_mode(&self) -> CompositionBitmapInterpolationMode {
988 self.bitmap_interpolation_mode.get()
989 }
990
991 pub fn set_bitmap_interpolation_mode(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: CompositionBitmapInterpolationMode) {
992 let old_value = self.bitmap_interpolation_mode.get();
993 let mut changed = false;
994 if old_value.differs(&value) {
995 ServerCompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changing(host);
996 changed = true;
997 }
998 host.set_value(
999 Self::id_of_bitmap_interpolation_mode_property().base(),
1000 ServerValueChange {
1001 equal: old_value.default_equals(&value),
1002 old_resource: None,
1003 new_resource: None,
1004 assign: &mut || self.bitmap_interpolation_mode.set(value),
1005 },
1006 );
1007 if changed {
1008 ServerCompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changed(host);
1009 }
1010 }
1011
1012 pub fn id_of_anchor_point_property() -> &'static CompositionPropertyOf<Vector> {
1014 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
1015 PROPERTY.get_or_init(|| {
1016 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
1017 "AnchorPoint",
1018 "ServerCompositionSurfaceBrush",
1019 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.get(),
1020 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.set(v),
1021 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.get())),
1022 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.set(v.cast_or_default::<Vector>())),
1023 )
1024 })
1025 }
1026
1027 pub fn anchor_point(&self) -> Vector {
1029 self.anchor_point.get()
1030 }
1031
1032 pub fn set_anchor_point(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
1033 self.anchor_point.set(value);
1034 host.remove_animation_for_property(Self::id_of_anchor_point_property().base());
1035 }
1036
1037 pub fn id_of_center_point_property() -> &'static CompositionPropertyOf<Vector> {
1039 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
1040 PROPERTY.get_or_init(|| {
1041 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
1042 "CenterPoint",
1043 "ServerCompositionSurfaceBrush",
1044 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.get(),
1045 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.set(v),
1046 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.get())),
1047 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.set(v.cast_or_default::<Vector>())),
1048 )
1049 })
1050 }
1051
1052 pub fn center_point(&self) -> Vector {
1054 self.center_point.get()
1055 }
1056
1057 pub fn set_center_point(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
1058 self.center_point.set(value);
1059 host.remove_animation_for_property(Self::id_of_center_point_property().base());
1060 }
1061
1062 pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector> {
1064 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
1065 PROPERTY.get_or_init(|| {
1066 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
1067 "Offset",
1068 "ServerCompositionSurfaceBrush",
1069 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.get(),
1070 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.set(v),
1071 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.get())),
1072 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.set(v.cast_or_default::<Vector>())),
1073 )
1074 })
1075 }
1076
1077 pub fn offset(&self) -> Vector {
1079 self.offset.get()
1080 }
1081
1082 pub fn set_offset(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
1083 self.offset.set(value);
1084 host.remove_animation_for_property(Self::id_of_offset_property().base());
1085 }
1086
1087 pub fn id_of_rotation_angle_property() -> &'static CompositionPropertyOf<f32> {
1089 static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
1090 PROPERTY.get_or_init(|| {
1091 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, f32>(
1092 "RotationAngle",
1093 "ServerCompositionSurfaceBrush",
1094 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.get(),
1095 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.set(v),
1096 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.get())),
1097 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.set(v.cast_or_default::<f32>())),
1098 )
1099 })
1100 }
1101
1102 pub fn rotation_angle(&self) -> f32 {
1104 self.rotation_angle.get()
1105 }
1106
1107 pub fn set_rotation_angle(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: f32) {
1108 self.rotation_angle.set(value);
1109 host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
1110 }
1111
1112 pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector> {
1114 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
1115 PROPERTY.get_or_init(|| {
1116 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
1117 "Scale",
1118 "ServerCompositionSurfaceBrush",
1119 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.get(),
1120 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.set(v),
1121 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.get())),
1122 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.set(v.cast_or_default::<Vector>())),
1123 )
1124 })
1125 }
1126
1127 pub fn scale(&self) -> Vector {
1129 self.scale.get()
1130 }
1131
1132 pub fn set_scale(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
1133 self.scale.set(value);
1134 host.remove_animation_for_property(Self::id_of_scale_property().base());
1135 }
1136
1137 pub fn id_of_transform_matrix_property() -> &'static CompositionPropertyOf<Matrix> {
1139 static PROPERTY: OnceLock<CompositionPropertyOf<Matrix>> = OnceLock::new();
1140 PROPERTY.get_or_init(|| {
1141 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Matrix>(
1142 "TransformMatrix",
1143 "ServerCompositionSurfaceBrush",
1144 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.get(),
1145 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.set(v),
1146 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.get())),
1147 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.set(v.cast_or_default::<Matrix>())),
1148 )
1149 })
1150 }
1151
1152 pub fn transform_matrix(&self) -> Matrix {
1154 self.transform_matrix.get()
1155 }
1156
1157 pub fn set_transform_matrix(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Matrix) {
1158 self.transform_matrix.set(value);
1159 host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
1160 }
1161
1162 pub fn id_of_snap_to_pixels_property() -> &'static CompositionPropertyOf<bool> {
1164 static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
1165 PROPERTY.get_or_init(|| {
1166 CompositionProperty::register::<ServerCompositionSurfaceBrushProps, bool>(
1167 "SnapToPixels",
1168 "ServerCompositionSurfaceBrush",
1169 |obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.get(),
1170 |obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.set(v),
1171 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.get())),
1172 None,
1173 )
1174 })
1175 }
1176
1177 pub fn snap_to_pixels(&self) -> bool {
1179 self.snap_to_pixels.get()
1180 }
1181
1182 pub fn set_snap_to_pixels(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: bool) {
1183 let old_value = self.snap_to_pixels.get();
1184 let mut changed = false;
1185 if old_value.differs(&value) {
1186 ServerCompositionSurfaceBrushHooks::on_snap_to_pixels_changing(host);
1187 changed = true;
1188 }
1189 host.set_value(
1190 Self::id_of_snap_to_pixels_property().base(),
1191 ServerValueChange {
1192 equal: old_value.default_equals(&value),
1193 old_resource: None,
1194 new_resource: None,
1195 assign: &mut || self.snap_to_pixels.set(value),
1196 },
1197 );
1198 if changed {
1199 ServerCompositionSurfaceBrushHooks::on_snap_to_pixels_changed(host);
1200 }
1201 }
1202
1203 pub fn deserialize_changes_core(
1206 &self,
1207 host: &dyn ServerCompositionSurfaceBrushHooks,
1208 reader: &mut BatchStreamReader<'_>,
1209 committed_at: Duration,
1210 ) {
1211 let compositor = host.server_compositor();
1212 self.base.deserialize_changes_core(host, reader, committed_at);
1213 ServerCompositionSurfaceBrushHooks::deserialize_changes_extra(host, reader);
1214 let changed = reader.read::<CompositionSurfaceBrushChangedFields>();
1215 if changed.contains(CompositionSurfaceBrushChangedFields::SURFACE) {
1216 let value = read_server_object(reader, compositor.as_ref());
1217 self.set_surface(host, value);
1218 }
1219 if changed.contains(CompositionSurfaceBrushChangedFields::STRETCH) {
1220 let value = reader.read::<CompositionStretch>();
1221 self.set_stretch(host, value);
1222 }
1223 if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED) {
1224 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1225 panic!("a batch starts an animation of `HorizontalAlignmentRatio` without an animation instance");
1226 };
1227 host.set_animated_value(
1228 Self::id_of_horizontal_alignment_ratio_property().base(),
1229 ExpressionVariant::create(self.horizontal_alignment_ratio.get()),
1230 committed_at,
1231 animation,
1232 );
1233 } else if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO) {
1234 let value = reader.read::<f32>();
1235 self.set_horizontal_alignment_ratio(host, value);
1236 }
1237 if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED) {
1238 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1239 panic!("a batch starts an animation of `VerticalAlignmentRatio` without an animation instance");
1240 };
1241 host.set_animated_value(
1242 Self::id_of_vertical_alignment_ratio_property().base(),
1243 ExpressionVariant::create(self.vertical_alignment_ratio.get()),
1244 committed_at,
1245 animation,
1246 );
1247 } else if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO) {
1248 let value = reader.read::<f32>();
1249 self.set_vertical_alignment_ratio(host, value);
1250 }
1251 if changed.contains(CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE) {
1252 let value = reader.read::<CompositionBitmapInterpolationMode>();
1253 self.set_bitmap_interpolation_mode(host, value);
1254 }
1255 if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED) {
1256 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1257 panic!("a batch starts an animation of `AnchorPoint` without an animation instance");
1258 };
1259 host.set_animated_value(
1260 Self::id_of_anchor_point_property().base(),
1261 ExpressionVariant::create(self.anchor_point.get()),
1262 committed_at,
1263 animation,
1264 );
1265 } else if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT) {
1266 let value = reader.read::<Vector>();
1267 self.set_anchor_point(host, value);
1268 }
1269 if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED) {
1270 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1271 panic!("a batch starts an animation of `CenterPoint` without an animation instance");
1272 };
1273 host.set_animated_value(
1274 Self::id_of_center_point_property().base(),
1275 ExpressionVariant::create(self.center_point.get()),
1276 committed_at,
1277 animation,
1278 );
1279 } else if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT) {
1280 let value = reader.read::<Vector>();
1281 self.set_center_point(host, value);
1282 }
1283 if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED) {
1284 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1285 panic!("a batch starts an animation of `Offset` without an animation instance");
1286 };
1287 host.set_animated_value(
1288 Self::id_of_offset_property().base(),
1289 ExpressionVariant::create(self.offset.get()),
1290 committed_at,
1291 animation,
1292 );
1293 } else if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET) {
1294 let value = reader.read::<Vector>();
1295 self.set_offset(host, value);
1296 }
1297 if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED) {
1298 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1299 panic!("a batch starts an animation of `RotationAngle` without an animation instance");
1300 };
1301 host.set_animated_value(
1302 Self::id_of_rotation_angle_property().base(),
1303 ExpressionVariant::create(self.rotation_angle.get()),
1304 committed_at,
1305 animation,
1306 );
1307 } else if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE) {
1308 let value = reader.read::<f32>();
1309 self.set_rotation_angle(host, value);
1310 }
1311 if changed.contains(CompositionSurfaceBrushChangedFields::SCALE_ANIMATED) {
1312 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1313 panic!("a batch starts an animation of `Scale` without an animation instance");
1314 };
1315 host.set_animated_value(
1316 Self::id_of_scale_property().base(),
1317 ExpressionVariant::create(self.scale.get()),
1318 committed_at,
1319 animation,
1320 );
1321 } else if changed.contains(CompositionSurfaceBrushChangedFields::SCALE) {
1322 let value = reader.read::<Vector>();
1323 self.set_scale(host, value);
1324 }
1325 if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED) {
1326 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
1327 panic!("a batch starts an animation of `TransformMatrix` without an animation instance");
1328 };
1329 host.set_animated_value(
1330 Self::id_of_transform_matrix_property().base(),
1331 ExpressionVariant::create(self.transform_matrix.get()),
1332 committed_at,
1333 animation,
1334 );
1335 } else if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX) {
1336 let value = reader.read::<Matrix>();
1337 self.set_transform_matrix(host, value);
1338 }
1339 if changed.contains(CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS) {
1340 let value = reader.read::<bool>();
1341 self.set_snap_to_pixels(host, value);
1342 }
1343 ServerCompositionSurfaceBrushHooks::on_fields_deserialized(host, changed);
1344 }
1345
1346 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
1349 if name == "HorizontalAlignmentRatio" {
1350 return Some(Self::id_of_horizontal_alignment_ratio_property().base());
1351 }
1352 if name == "VerticalAlignmentRatio" {
1353 return Some(Self::id_of_vertical_alignment_ratio_property().base());
1354 }
1355 if name == "AnchorPoint" {
1356 return Some(Self::id_of_anchor_point_property().base());
1357 }
1358 if name == "CenterPoint" {
1359 return Some(Self::id_of_center_point_property().base());
1360 }
1361 if name == "Offset" {
1362 return Some(Self::id_of_offset_property().base());
1363 }
1364 if name == "RotationAngle" {
1365 return Some(Self::id_of_rotation_angle_property().base());
1366 }
1367 if name == "Scale" {
1368 return Some(Self::id_of_scale_property().base());
1369 }
1370 if name == "TransformMatrix" {
1371 return Some(Self::id_of_transform_matrix_property().base());
1372 }
1373 if name == "SnapToPixels" {
1374 return Some(Self::id_of_snap_to_pixels_property().base());
1375 }
1376 ServerCompositionBrushProps::get_composition_property(name)
1377 }
1378}