1use std::any::Any;
14use std::rc::Rc;
15use std::sync::Arc;
16
17use inset_animation::AnyAnimation;
18use inset_embedder::{
19 BlendMode, Clip, Color, FillRule, ImageFilter, Matrix4, Offset, Paint, Path, PathBuilder,
20 RRect, RSuperellipse, Rect, Size, TextBaseline, rsuperellipse_radii_elliptical, valo::Point,
21};
22use inset_foundation::{App, Handle, Listenable, Listener};
23use inset_gestures::{
24 PointerCancelEventListener, PointerDownEventListener, PointerEnterEventListener, PointerEvent,
25 PointerExitEventListener, PointerHoverEventListener, PointerMoveEventListener,
26 PointerPanZoomEndEventListener, PointerPanZoomStartEventListener,
27 PointerPanZoomUpdateEventListener, PointerSignalEventListener, PointerUpEventListener,
28};
29use inset_painting::{
30 Alignment, AlignmentGeometry, BorderRadiusGeometry, BoxFit, BoxPainter, ClipContext,
31 Decoration, ImageConfiguration, ShapeBorder, TextDirection, apply_box_fit, get_as_translation,
32};
33use inset_services::{MouseCursor, MouseCursorRef, MouseTrackerAnnotation};
34
35use crate::box_::{
36 AnyRenderBox, BoxConstraints, BoxHitTestEntry, BoxHitTestResult, RenderBox, RenderBoxBase,
37 RenderBoxData,
38};
39use crate::image_filter_config::{ImageFilterConfig, ImageFilterContext};
40use crate::layer::{
41 AnnotatedRegionLayer, BackdropFilterLayer, BackdropKey, ClipPathLayer, ClipRRectLayer,
42 ClipRectLayer, ContainerLayer, FollowerLayer, LayerHandle, LayerLink, LeaderLayer,
43 OffsetLayerMixin, OpacityLayer, TransformLayer,
44};
45use crate::layout_helper::{ChildLayoutHelper, ChildLayouter};
46use crate::object::{
47 AnyRenderObject, Constraints, EmptyParentData, RenderHandle, RenderObject, RenderObjectData,
48 RenderObjectWithChildData, RenderObjectWithChildMixin,
49};
50use crate::painting_context::PaintingContext;
51use crate::pipeline_owner::PipelineOwner;
52
53pub trait RenderProxyBoxMixin:
59 RenderObjectWithChildMixin<ChildType = AnyRenderBox> + RenderBox
60{
61 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
63 if child.parent_data(app).is_none() {
64 child.set_parent_data(app, EmptyParentData);
65 }
66 }
67
68 fn apply_paint_transform(
70 self: RenderHandle<Self>,
71 app: &App,
72 child: AnyRenderObject,
73 transform: &mut Matrix4,
74 ) {
75 let _ = (app, child, transform);
76 }
77
78 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
80 match self.child(app) {
81 Some(child) => child.get_min_intrinsic_width(app, height),
82 None => 0.0,
83 }
84 }
85
86 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
88 match self.child(app) {
89 Some(child) => child.get_max_intrinsic_width(app, height),
90 None => 0.0,
91 }
92 }
93
94 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
96 match self.child(app) {
97 Some(child) => child.get_min_intrinsic_height(app, width),
98 None => 0.0,
99 }
100 }
101
102 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
104 match self.child(app) {
105 Some(child) => child.get_max_intrinsic_height(app, width),
106 None => 0.0,
107 }
108 }
109
110 fn compute_distance_to_actual_baseline(
112 self: RenderHandle<Self>,
113 app: &mut App,
114 baseline: TextBaseline,
115 ) -> Option<f64> {
116 self.child(app)
117 .and_then(|child| child.get_distance_to_actual_baseline(app, baseline))
118 }
119
120 fn compute_dry_baseline(
122 self: RenderHandle<Self>,
123 app: &mut App,
124 constraints: BoxConstraints,
125 baseline: TextBaseline,
126 ) -> Option<f64> {
127 self.child(app)
128 .and_then(|child| child.get_dry_baseline(app, constraints, baseline))
129 }
130
131 fn compute_dry_layout(
134 self: RenderHandle<Self>,
135 app: &mut App,
136 constraints: BoxConstraints,
137 ) -> Size {
138 match self.child(app) {
139 Some(child) => child.get_dry_layout(app, constraints),
140 None => self.compute_size_for_no_child(app, constraints),
141 }
142 }
143
144 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
146 let constraints = self.constraints(app);
147 let size = match self.child(app) {
148 Some(child) => {
149 child.layout(app, constraints, true);
150 child.size(app)
151 }
152 None => self.compute_size_for_no_child(app, constraints),
153 };
154 self.set_size(app, size);
155 }
156
157 fn compute_size_for_no_child(
159 self: RenderHandle<Self>,
160 _app: &App,
161 constraints: BoxConstraints,
162 ) -> Size {
163 constraints.smallest()
164 }
165
166 fn hit_test_children(
168 self: RenderHandle<Self>,
169 app: &mut App,
170 result: &mut BoxHitTestResult<'_>,
171 position: Offset,
172 ) -> bool {
173 match self.child(app) {
174 Some(child) => child.hit_test(app, result, position),
175 None => false,
176 }
177 }
178
179 fn paint(
181 self: RenderHandle<Self>,
182 app: &mut App,
183 context: &mut PaintingContext,
184 offset: Offset,
185 ) {
186 let Some(child) = self.child(app) else {
187 return;
188 };
189 context.paint_child(app, child.as_object(), offset);
190 }
191}
192
193pub trait RenderProxyBoxWithHitTestBehavior: RenderProxyBoxMixin {
198 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior;
201
202 fn hit_test(
204 self: RenderHandle<Self>,
205 app: &mut App,
206 result: &mut BoxHitTestResult<'_>,
207 position: Offset,
208 ) -> bool {
209 let mut hit_target = false;
210 if self.size(app).contains(position) {
211 hit_target = RenderBox::hit_test_children(self, app, result, position)
212 || RenderBox::hit_test_self(self, app, position);
213 if hit_target || self.behavior(app) == HitTestBehavior::Translucent {
214 result.add(BoxHitTestEntry::new(self.as_box(), position).into());
215 }
216 }
217 hit_target
218 }
219
220 fn hit_test_self(self: RenderHandle<Self>, app: &App, _position: Offset) -> bool {
222 self.behavior(app) == HitTestBehavior::Opaque
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228pub enum HitTestBehavior {
229 DeferToChild,
232
233 Opaque,
237
238 Translucent,
241}
242
243pub struct RenderConstrainedBox {
245 render_object: RenderObjectData,
246 render_box: RenderBoxData,
247 child: RenderObjectWithChildData<AnyRenderBox>,
248 additional_constraints: BoxConstraints,
249}
250
251impl RenderConstrainedBox {
252 pub fn new(
256 app: &mut App,
257 additional_constraints: BoxConstraints,
258 child: Option<AnyRenderBox>,
259 ) -> RenderHandle<RenderConstrainedBox> {
260 debug_assert!(additional_constraints.debug_assert_is_valid(false));
261 let this = RenderHandle::new_box(
262 app,
263 RenderConstrainedBox {
264 render_object: RenderObjectData::new(),
265 render_box: RenderBoxData::new(),
266 child: RenderObjectWithChildData::new(),
267 additional_constraints,
268 },
269 );
270 this.set_child(app, child);
271 this
272 }
273
274 pub fn additional_constraints(self: RenderHandle<Self>, app: &App) -> BoxConstraints {
276 self.get(app).additional_constraints
277 }
278
279 pub fn set_additional_constraints(
281 self: RenderHandle<Self>,
282 app: &mut App,
283 value: BoxConstraints,
284 ) {
285 debug_assert!(value.debug_assert_is_valid(false));
286 if self.get(app).additional_constraints == value {
287 return;
288 }
289 self.get_mut(app).additional_constraints = value;
290 self.mark_needs_layout(app);
291 }
292}
293
294impl RenderObjectWithChildMixin for RenderConstrainedBox {
295 type ChildType = AnyRenderBox;
296
297 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
298 &self.get(app).child
299 }
300
301 fn child_data_mut(
302 self: RenderHandle<Self>,
303 app: &mut App,
304 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
305 &mut self.get_mut(app).child
306 }
307}
308
309impl RenderProxyBoxMixin for RenderConstrainedBox {}
310
311impl RenderObject for RenderConstrainedBox {
312 crate::render_object_accessors!();
313
314 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
315 let constraints = self.constraints(app);
316 let additional = self.get(app).additional_constraints;
317 if let Some(child) = self.child(app) {
318 child.layout(app, additional.enforce(constraints), true);
319 self.set_size(app, child.size(app));
320 } else {
321 self.set_size(app, additional.enforce(constraints).constrain(Size::ZERO));
322 }
323 }
324
325 fn paint(
326 self: RenderHandle<Self>,
327 app: &mut App,
328 context: &mut PaintingContext,
329 offset: Offset,
330 ) {
331 RenderProxyBoxMixin::paint(self, app, context, offset);
332 }
333
334 fn visit_children(
335 self: RenderHandle<Self>,
336 app: &App,
337 visitor: &mut dyn FnMut(AnyRenderObject),
338 ) {
339 if let Some(child) = self.child(app) {
340 visitor(child.as_object());
341 }
342 }
343}
344
345impl RenderBox for RenderConstrainedBox {
346 crate::render_box_accessors!();
347
348 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
349 RenderProxyBoxMixin::setup_parent_data(self, app, child);
350 }
351
352 fn apply_paint_transform(
353 self: RenderHandle<Self>,
354 app: &App,
355 child: AnyRenderObject,
356 transform: &mut Matrix4,
357 ) {
358 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
359 }
360
361 fn hit_test_children(
362 self: RenderHandle<Self>,
363 app: &mut App,
364 result: &mut BoxHitTestResult<'_>,
365 position: Offset,
366 ) -> bool {
367 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
368 }
369
370 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
371 let additional = self.get(app).additional_constraints;
372 if additional.has_bounded_width() && additional.has_tight_width() {
373 return additional.min_width;
374 }
375 let width = RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height);
376 debug_assert!(width.is_finite());
377 if additional.has_infinite_width() {
378 width
379 } else {
380 additional.constrain_width(width)
381 }
382 }
383
384 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
385 let additional = self.get(app).additional_constraints;
386 if additional.has_bounded_width() && additional.has_tight_width() {
387 return additional.min_width;
388 }
389 let width = RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height);
390 debug_assert!(width.is_finite());
391 if additional.has_infinite_width() {
392 width
393 } else {
394 additional.constrain_width(width)
395 }
396 }
397
398 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
399 let additional = self.get(app).additional_constraints;
400 if additional.has_bounded_height() && additional.has_tight_height() {
401 return additional.min_height;
402 }
403 let height = RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width);
404 debug_assert!(height.is_finite());
405 if additional.has_infinite_height() {
406 height
407 } else {
408 additional.constrain_height(height)
409 }
410 }
411
412 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
413 let additional = self.get(app).additional_constraints;
414 if additional.has_bounded_height() && additional.has_tight_height() {
415 return additional.min_height;
416 }
417 let height = RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width);
418 debug_assert!(height.is_finite());
419 if additional.has_infinite_height() {
420 height
421 } else {
422 additional.constrain_height(height)
423 }
424 }
425
426 fn compute_distance_to_actual_baseline(
427 self: RenderHandle<Self>,
428 app: &mut App,
429 baseline: TextBaseline,
430 ) -> Option<f64> {
431 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
432 }
433
434 fn compute_dry_baseline(
435 self: RenderHandle<Self>,
436 app: &mut App,
437 constraints: BoxConstraints,
438 baseline: TextBaseline,
439 ) -> Option<f64> {
440 let additional = self.get(app).additional_constraints;
441 self.child(app).and_then(|child| {
442 child.get_dry_baseline(app, additional.enforce(constraints), baseline)
443 })
444 }
445
446 fn compute_dry_layout(
447 self: RenderHandle<Self>,
448 app: &mut App,
449 constraints: BoxConstraints,
450 ) -> Size {
451 let additional = self.get(app).additional_constraints;
452 match self.child(app) {
453 Some(child) => child.get_dry_layout(app, additional.enforce(constraints)),
454 None => additional.enforce(constraints).constrain(Size::ZERO),
455 }
456 }
457}
458
459pub struct RenderOpacity {
469 render_object: RenderObjectData,
470 render_box: RenderBoxData,
471 child: RenderObjectWithChildData<AnyRenderBox>,
472 alpha: i32,
473 opacity: f64,
474}
475
476impl RenderOpacity {
477 pub fn new(app: &mut App, opacity: f64, child: Option<AnyRenderBox>) -> RenderHandle<Self> {
481 debug_assert!((0.0..=1.0).contains(&opacity));
482 let this = RenderHandle::new_box(
483 app,
484 RenderOpacity {
485 render_object: RenderObjectData::new(),
486 render_box: RenderBoxData::new(),
487 child: RenderObjectWithChildData::new(),
488 alpha: Color::get_alpha_from_opacity(opacity),
489 opacity,
490 },
491 );
492 this.set_child(app, child);
493 this
494 }
495
496 pub fn opacity(self: RenderHandle<Self>, app: &App) -> f64 {
505 self.get(app).opacity
506 }
507
508 pub fn set_opacity(self: RenderHandle<Self>, app: &mut App, value: f64) {
510 debug_assert!((0.0..=1.0).contains(&value));
511 if self.get(app).opacity == value {
512 return;
513 }
514 let did_need_compositing = self.always_needs_compositing(app);
515 let this = self.get_mut(app);
516 this.opacity = value;
517 this.alpha = Color::get_alpha_from_opacity(value);
518 if did_need_compositing != self.always_needs_compositing(app) {
519 self.mark_needs_compositing_bits_update(app);
520 }
521 self.mark_needs_composited_layer_update(app);
522 }
523}
524
525impl RenderObjectWithChildMixin for RenderOpacity {
526 type ChildType = AnyRenderBox;
527
528 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
529 &self.get(app).child
530 }
531
532 fn child_data_mut(
533 self: RenderHandle<Self>,
534 app: &mut App,
535 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
536 &mut self.get_mut(app).child
537 }
538}
539
540impl RenderProxyBoxMixin for RenderOpacity {}
541
542impl RenderObject for RenderOpacity {
543 crate::render_object_accessors!();
544
545 fn always_needs_compositing(self: RenderHandle<Self>, app: &App) -> bool {
546 self.child(app).is_some() && self.get(app).alpha > 0
547 }
548
549 fn is_repaint_boundary(self: RenderHandle<Self>, app: &App) -> bool {
550 self.always_needs_compositing(app)
551 }
552
553 fn update_composited_layer(
554 self: RenderHandle<Self>,
555 app: &mut App,
556 old_layer: Option<crate::AnyOffsetLayer>,
557 ) -> crate::AnyOffsetLayer {
558 let layer = match old_layer {
559 Some(old) => app
560 .handle::<OpacityLayer>(old.id())
561 .expect("RenderOpacity reuses an OpacityLayer"),
562 None => OpacityLayer::new(app),
563 };
564 layer.set_alpha(app, self.get(app).alpha);
565 layer.as_offset_layer()
566 }
567
568 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
569 RenderProxyBoxMixin::perform_layout(self, app);
570 }
571
572 fn paint(
573 self: RenderHandle<Self>,
574 app: &mut App,
575 context: &mut PaintingContext,
576 offset: Offset,
577 ) {
578 if self.child(app).is_none() || self.get(app).alpha == 0 {
579 return;
580 }
581 RenderProxyBoxMixin::paint(self, app, context, offset);
582 }
583
584 fn visit_children(
585 self: RenderHandle<Self>,
586 app: &App,
587 visitor: &mut dyn FnMut(AnyRenderObject),
588 ) {
589 if let Some(child) = self.child(app) {
590 visitor(child.as_object());
591 }
592 }
593}
594
595impl RenderBox for RenderOpacity {
596 crate::render_box_accessors!();
597
598 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
599 RenderProxyBoxMixin::setup_parent_data(self, app, child);
600 }
601
602 fn apply_paint_transform(
603 self: RenderHandle<Self>,
604 app: &App,
605 child: AnyRenderObject,
606 transform: &mut Matrix4,
607 ) {
608 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
609 }
610
611 fn hit_test_children(
612 self: RenderHandle<Self>,
613 app: &mut App,
614 result: &mut BoxHitTestResult<'_>,
615 position: Offset,
616 ) -> bool {
617 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
618 }
619
620 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
621 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
622 }
623
624 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
625 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
626 }
627
628 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
629 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
630 }
631
632 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
633 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
634 }
635
636 fn compute_distance_to_actual_baseline(
637 self: RenderHandle<Self>,
638 app: &mut App,
639 baseline: TextBaseline,
640 ) -> Option<f64> {
641 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
642 }
643
644 fn compute_dry_baseline(
645 self: RenderHandle<Self>,
646 app: &mut App,
647 constraints: BoxConstraints,
648 baseline: TextBaseline,
649 ) -> Option<f64> {
650 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
651 }
652
653 fn compute_dry_layout(
654 self: RenderHandle<Self>,
655 app: &mut App,
656 constraints: BoxConstraints,
657 ) -> Size {
658 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
659 }
660}
661
662pub struct RenderLeaderLayer {
667 render_object: RenderObjectData,
668 render_box: RenderBoxData,
669 child: RenderObjectWithChildData<AnyRenderBox>,
670 link: Handle<LayerLink>,
671 previous_layout_size: Option<Size>,
673}
674
675impl RenderLeaderLayer {
676 pub fn new(
677 app: &mut App,
678 link: Handle<LayerLink>,
679 child: Option<AnyRenderBox>,
680 ) -> RenderHandle<Self> {
681 let this = RenderHandle::new_box(
682 app,
683 RenderLeaderLayer {
684 render_object: RenderObjectData::new(),
685 render_box: RenderBoxData::new(),
686 child: RenderObjectWithChildData::new(),
687 link,
688 previous_layout_size: None,
689 },
690 );
691 this.set_child(app, child);
692 this
693 }
694
695 pub fn link(self: RenderHandle<Self>, app: &App) -> Handle<LayerLink> {
698 self.get(app).link
699 }
700
701 pub fn set_link(self: RenderHandle<Self>, app: &mut App, value: Handle<LayerLink>) {
703 let link = self.get(app).link;
704 if link == value {
705 return;
706 }
707 let old = app.get_mut(link);
708 old.leader_size = None;
709 self.get_mut(app).link = value;
710 if let Some(size) = self.get(app).previous_layout_size {
711 app.get_mut(value).leader_size = Some(size);
712 }
713 self.mark_needs_paint(app);
714 }
715}
716
717impl RenderObjectWithChildMixin for RenderLeaderLayer {
718 type ChildType = AnyRenderBox;
719
720 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
721 &self.get(app).child
722 }
723
724 fn child_data_mut(
725 self: RenderHandle<Self>,
726 app: &mut App,
727 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
728 &mut self.get_mut(app).child
729 }
730}
731
732impl RenderProxyBoxMixin for RenderLeaderLayer {}
733
734impl RenderObject for RenderLeaderLayer {
735 crate::render_object_accessors!();
736
737 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
738 true
739 }
740
741 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
742 RenderProxyBoxMixin::perform_layout(self, app);
743 let size = self.size(app);
744 self.get_mut(app).previous_layout_size = Some(size);
745 let link = self.get(app).link;
746 app.get_mut(link).leader_size = Some(size);
747 }
748
749 fn paint(
750 self: RenderHandle<Self>,
751 app: &mut App,
752 context: &mut PaintingContext,
753 offset: Offset,
754 ) {
755 let link = self.get(app).link;
756 let layer = match self.as_object().layer_as::<LeaderLayer>(app) {
757 None => {
758 let layer = LeaderLayer::new(app, link);
759 layer.set_offset(app, offset);
760 self.as_object()
761 .set_layer(app, Some(layer.as_container_layer()));
762 layer
763 }
764 Some(layer) => {
765 layer.set_link(app, link);
766 layer.set_offset(app, offset);
767 layer
768 }
769 };
770 context.push_layer(
771 app,
772 layer.as_container_layer(),
773 |app, context, offset| {
774 RenderProxyBoxMixin::paint(self, app, context, offset);
775 },
776 Offset::ZERO,
777 None,
778 );
779 }
780
781 fn visit_children(
782 self: RenderHandle<Self>,
783 app: &App,
784 visitor: &mut dyn FnMut(AnyRenderObject),
785 ) {
786 if let Some(child) = self.child(app) {
787 visitor(child.as_object());
788 }
789 }
790}
791
792impl RenderBox for RenderLeaderLayer {
793 crate::render_box_accessors!();
794
795 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
796 RenderProxyBoxMixin::setup_parent_data(self, app, child);
797 }
798
799 fn apply_paint_transform(
800 self: RenderHandle<Self>,
801 app: &App,
802 child: AnyRenderObject,
803 transform: &mut Matrix4,
804 ) {
805 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
806 }
807
808 fn hit_test_children(
809 self: RenderHandle<Self>,
810 app: &mut App,
811 result: &mut BoxHitTestResult<'_>,
812 position: Offset,
813 ) -> bool {
814 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
815 }
816
817 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
818 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
819 }
820
821 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
822 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
823 }
824
825 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
826 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
827 }
828
829 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
830 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
831 }
832
833 fn compute_distance_to_actual_baseline(
834 self: RenderHandle<Self>,
835 app: &mut App,
836 baseline: TextBaseline,
837 ) -> Option<f64> {
838 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
839 }
840
841 fn compute_dry_baseline(
842 self: RenderHandle<Self>,
843 app: &mut App,
844 constraints: BoxConstraints,
845 baseline: TextBaseline,
846 ) -> Option<f64> {
847 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
848 }
849
850 fn compute_dry_layout(
851 self: RenderHandle<Self>,
852 app: &mut App,
853 constraints: BoxConstraints,
854 ) -> Size {
855 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
856 }
857}
858
859pub struct RenderFollowerLayer {
864 render_object: RenderObjectData,
865 render_box: RenderBoxData,
866 child: RenderObjectWithChildData<AnyRenderBox>,
867 link: Handle<LayerLink>,
868 show_when_unlinked: bool,
869 offset: Offset,
870 leader_anchor: Alignment,
871 follower_anchor: Alignment,
872}
873
874impl RenderFollowerLayer {
875 pub fn new(
876 app: &mut App,
877 link: Handle<LayerLink>,
878 show_when_unlinked: bool,
879 offset: Offset,
880 leader_anchor: Alignment,
881 follower_anchor: Alignment,
882 child: Option<AnyRenderBox>,
883 ) -> RenderHandle<Self> {
884 let this = RenderHandle::new_box(
885 app,
886 RenderFollowerLayer {
887 render_object: RenderObjectData::new(),
888 render_box: RenderBoxData::new(),
889 child: RenderObjectWithChildData::new(),
890 link,
891 show_when_unlinked,
892 offset,
893 leader_anchor,
894 follower_anchor,
895 },
896 );
897 this.set_child(app, child);
898 this
899 }
900
901 pub fn link(self: RenderHandle<Self>, app: &App) -> Handle<LayerLink> {
903 self.get(app).link
904 }
905
906 pub fn set_link(self: RenderHandle<Self>, app: &mut App, value: Handle<LayerLink>) {
908 if self.get(app).link == value {
909 return;
910 }
911 self.get_mut(app).link = value;
912 self.mark_needs_paint(app);
913 }
914
915 pub fn show_when_unlinked(self: RenderHandle<Self>, app: &App) -> bool {
918 self.get(app).show_when_unlinked
919 }
920
921 pub fn set_show_when_unlinked(self: RenderHandle<Self>, app: &mut App, value: bool) {
923 if self.get(app).show_when_unlinked == value {
924 return;
925 }
926 self.get_mut(app).show_when_unlinked = value;
927 self.mark_needs_paint(app);
928 }
929
930 pub fn offset(self: RenderHandle<Self>, app: &App) -> Offset {
933 self.get(app).offset
934 }
935
936 pub fn set_offset(self: RenderHandle<Self>, app: &mut App, value: Offset) {
938 if self.get(app).offset == value {
939 return;
940 }
941 self.get_mut(app).offset = value;
942 self.mark_needs_paint(app);
943 }
944
945 pub fn leader_anchor(self: RenderHandle<Self>, app: &App) -> Alignment {
950 self.get(app).leader_anchor
951 }
952
953 pub fn set_leader_anchor(self: RenderHandle<Self>, app: &mut App, value: Alignment) {
955 if self.get(app).leader_anchor == value {
956 return;
957 }
958 self.get_mut(app).leader_anchor = value;
959 self.mark_needs_paint(app);
960 }
961
962 pub fn follower_anchor(self: RenderHandle<Self>, app: &App) -> Alignment {
966 self.get(app).follower_anchor
967 }
968
969 pub fn set_follower_anchor(self: RenderHandle<Self>, app: &mut App, value: Alignment) {
971 if self.get(app).follower_anchor == value {
972 return;
973 }
974 self.get_mut(app).follower_anchor = value;
975 self.mark_needs_paint(app);
976 }
977
978 pub fn current_transform(self: RenderHandle<Self>, app: &App) -> Matrix4 {
983 self.as_object()
984 .layer_as::<FollowerLayer>(app)
985 .and_then(|layer| layer.get_last_transform(app))
986 .unwrap_or(Matrix4::IDENTITY)
987 }
988}
989
990impl RenderObjectWithChildMixin for RenderFollowerLayer {
991 type ChildType = AnyRenderBox;
992
993 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
994 &self.get(app).child
995 }
996
997 fn child_data_mut(
998 self: RenderHandle<Self>,
999 app: &mut App,
1000 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1001 &mut self.get_mut(app).child
1002 }
1003}
1004
1005impl RenderProxyBoxMixin for RenderFollowerLayer {}
1006
1007impl RenderObject for RenderFollowerLayer {
1008 crate::render_object_accessors!();
1009
1010 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
1011 true
1012 }
1013
1014 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1015 RenderProxyBoxMixin::perform_layout(self, app);
1016 }
1017
1018 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
1020 self.as_object().set_layer(app, None);
1021 if let Some(child) = self.child(app) {
1022 child.as_object().detach(app);
1023 }
1024 }
1025
1026 fn paint(
1027 self: RenderHandle<Self>,
1028 app: &mut App,
1029 context: &mut PaintingContext,
1030 offset: Offset,
1031 ) {
1032 let link = self.get(app).link;
1033 let leader_size = app.get(link).leader_size;
1034 debug_assert!(
1035 leader_size.is_some()
1036 || link.leader(app).is_none()
1037 || self.get(app).leader_anchor == Alignment::TOP_LEFT,
1038 "a leader size is required when leader_anchor is not Alignment::TOP_LEFT"
1039 );
1040 let this = self.get(app);
1041 let effective_linked_offset = match leader_size {
1042 None => this.offset,
1043 Some(leader_size) => {
1044 this.leader_anchor.along_size(leader_size)
1045 - this.follower_anchor.along_size(self.size(app))
1046 + this.offset
1047 }
1048 };
1049 let show_when_unlinked = this.show_when_unlinked;
1050 let layer = match self.as_object().layer_as::<FollowerLayer>(app) {
1051 None => {
1052 let layer = FollowerLayer::new(app, link);
1053 layer.set_show_when_unlinked(app, show_when_unlinked);
1054 layer.set_linked_offset(app, effective_linked_offset);
1055 layer.set_unlinked_offset(app, offset);
1056 self.as_object()
1057 .set_layer(app, Some(layer.as_container_layer()));
1058 layer
1059 }
1060 Some(layer) => {
1061 layer.set_link(app, link);
1062 layer.set_show_when_unlinked(app, show_when_unlinked);
1063 layer.set_linked_offset(app, effective_linked_offset);
1064 layer.set_unlinked_offset(app, offset);
1065 layer
1066 }
1067 };
1068 context.push_layer(
1069 app,
1070 layer.as_container_layer(),
1071 |app, context, offset| {
1072 RenderProxyBoxMixin::paint(self, app, context, offset);
1073 },
1074 Offset::ZERO,
1075 Some(Rect::from_ltrb(
1076 f64::NEG_INFINITY,
1077 f64::NEG_INFINITY,
1078 f64::INFINITY,
1079 f64::INFINITY,
1080 )),
1081 );
1082 }
1083
1084 fn visit_children(
1085 self: RenderHandle<Self>,
1086 app: &App,
1087 visitor: &mut dyn FnMut(AnyRenderObject),
1088 ) {
1089 if let Some(child) = self.child(app) {
1090 visitor(child.as_object());
1091 }
1092 }
1093}
1094
1095impl RenderBox for RenderFollowerLayer {
1096 crate::render_box_accessors!();
1097
1098 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1099 RenderProxyBoxMixin::setup_parent_data(self, app, child);
1100 }
1101
1102 fn apply_paint_transform(
1103 self: RenderHandle<Self>,
1104 app: &App,
1105 _child: AnyRenderObject,
1106 transform: &mut Matrix4,
1107 ) {
1108 *transform = transform.then(&self.current_transform(app));
1109 }
1110
1111 fn hit_test(
1115 self: RenderHandle<Self>,
1116 app: &mut App,
1117 result: &mut BoxHitTestResult<'_>,
1118 position: Offset,
1119 ) -> bool {
1120 let link = self.get(app).link;
1121 if link.leader(app).is_none() && !self.get(app).show_when_unlinked {
1122 return false;
1123 }
1124 RenderBox::hit_test_children(self, app, result, position)
1125 }
1126
1127 fn hit_test_children(
1128 self: RenderHandle<Self>,
1129 app: &mut App,
1130 result: &mut BoxHitTestResult<'_>,
1131 position: Offset,
1132 ) -> bool {
1133 let transform = self.current_transform(app);
1134 result.add_with_paint_transform(Some(transform), position, |result, position| {
1135 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
1136 })
1137 }
1138
1139 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1140 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
1141 }
1142
1143 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1144 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
1145 }
1146
1147 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1148 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
1149 }
1150
1151 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1152 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
1153 }
1154
1155 fn compute_distance_to_actual_baseline(
1156 self: RenderHandle<Self>,
1157 app: &mut App,
1158 baseline: TextBaseline,
1159 ) -> Option<f64> {
1160 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
1161 }
1162
1163 fn compute_dry_baseline(
1164 self: RenderHandle<Self>,
1165 app: &mut App,
1166 constraints: BoxConstraints,
1167 baseline: TextBaseline,
1168 ) -> Option<f64> {
1169 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
1170 }
1171
1172 fn compute_dry_layout(
1173 self: RenderHandle<Self>,
1174 app: &mut App,
1175 constraints: BoxConstraints,
1176 ) -> Size {
1177 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
1178 }
1179}
1180
1181pub struct RenderAnimatedOpacityData {
1183 alpha: Option<i32>,
1184 currently_is_repaint_boundary: Option<bool>,
1185 opacity: Option<AnyAnimation<f64>>,
1186}
1187
1188impl RenderAnimatedOpacityData {
1189 pub const fn new() -> RenderAnimatedOpacityData {
1191 RenderAnimatedOpacityData {
1192 alpha: None,
1193 currently_is_repaint_boundary: None,
1194 opacity: None,
1195 }
1196 }
1197}
1198
1199impl Default for RenderAnimatedOpacityData {
1200 fn default() -> RenderAnimatedOpacityData {
1201 RenderAnimatedOpacityData::new()
1202 }
1203}
1204
1205pub trait RenderAnimatedOpacityMixin:
1214 RenderObjectWithChildMixin<ChildType = AnyRenderBox> + RenderBox
1215{
1216 fn animated_opacity_data(self: RenderHandle<Self>, app: &App) -> &RenderAnimatedOpacityData;
1218
1219 fn animated_opacity_data_mut(
1221 self: RenderHandle<Self>,
1222 app: &mut App,
1223 ) -> &mut RenderAnimatedOpacityData;
1224
1225 fn is_repaint_boundary(self: RenderHandle<Self>, app: &App) -> bool {
1227 self.child(app).is_some()
1228 && self
1229 .animated_opacity_data(app)
1230 .currently_is_repaint_boundary
1231 .expect("set by the opacity setter")
1232 }
1233
1234 fn update_composited_layer(
1236 self: RenderHandle<Self>,
1237 app: &mut App,
1238 old_layer: Option<crate::AnyOffsetLayer>,
1239 ) -> crate::AnyOffsetLayer {
1240 let alpha = self
1241 .animated_opacity_data(app)
1242 .alpha
1243 .expect("set by the opacity setter");
1244 let layer = match old_layer {
1245 Some(old) => app
1246 .handle::<OpacityLayer>(old.id())
1247 .expect("RenderAnimatedOpacity reuses an OpacityLayer"),
1248 None => OpacityLayer::new(app),
1249 };
1250 layer.set_alpha(app, alpha);
1251 layer.as_offset_layer()
1252 }
1253
1254 fn opacity(self: RenderHandle<Self>, app: &App) -> AnyAnimation<f64> {
1259 self.animated_opacity_data(app)
1260 .opacity
1261 .expect("set by the constructor")
1262 }
1263
1264 fn set_opacity(self: RenderHandle<Self>, app: &mut App, value: AnyAnimation<f64>) {
1266 if self.animated_opacity_data(app).opacity == Some(value) {
1267 return;
1268 }
1269 if self.attached(app)
1270 && let Some(opacity) = self.animated_opacity_data(app).opacity
1271 {
1272 opacity.remove_listener(app, &self.opacity_listener());
1273 }
1274 self.animated_opacity_data_mut(app).opacity = Some(value);
1275 if self.attached(app) {
1276 value.add_listener(app, self.opacity_listener());
1277 }
1278 self.update_opacity(app);
1279 }
1280
1281 fn did_attach(self: RenderHandle<Self>, app: &mut App) {
1283 self.opacity(app).add_listener(app, self.opacity_listener());
1284 self.update_opacity(app); }
1286
1287 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
1289 self.opacity(app)
1290 .remove_listener(app, &self.opacity_listener());
1291 }
1292
1293 fn opacity_listener(self: RenderHandle<Self>) -> Listener {
1295 Listener::handle_method(self.handle(), update_opacity::<Self>)
1296 }
1297
1298 fn update_opacity(self: RenderHandle<Self>, app: &mut App) {
1300 let old_alpha = self.animated_opacity_data(app).alpha;
1301 let alpha = Color::get_alpha_from_opacity(self.opacity(app).value(app));
1302 self.animated_opacity_data_mut(app).alpha = Some(alpha);
1303 if old_alpha != Some(alpha) {
1304 let was_repaint_boundary = self
1305 .animated_opacity_data(app)
1306 .currently_is_repaint_boundary;
1307 self.animated_opacity_data_mut(app)
1308 .currently_is_repaint_boundary = Some(alpha > 0);
1309 if self.child(app).is_some() && was_repaint_boundary != Some(alpha > 0) {
1311 self.mark_needs_compositing_bits_update(app);
1312 }
1313 self.mark_needs_composited_layer_update(app);
1314 }
1315 }
1316
1317 fn paint(self: RenderHandle<Self>, app: &mut App, context: &mut PaintingContext, offset: Offset)
1319 where
1320 Self: RenderProxyBoxMixin,
1321 {
1322 if self.animated_opacity_data(app).alpha == Some(0) {
1323 return;
1324 }
1325 RenderProxyBoxMixin::paint(self, app, context, offset);
1326 }
1327}
1328
1329fn update_opacity<T: RenderAnimatedOpacityMixin>(this: Handle<T>, app: &mut App) {
1330 RenderAnimatedOpacityMixin::update_opacity(RenderHandle::from_handle(this), app);
1331}
1332
1333pub struct RenderAnimatedOpacity {
1338 render_object: RenderObjectData,
1339 render_box: RenderBoxData,
1340 child: RenderObjectWithChildData<AnyRenderBox>,
1341 animated_opacity: RenderAnimatedOpacityData,
1342}
1343
1344impl RenderAnimatedOpacity {
1345 pub fn new(
1347 app: &mut App,
1348 opacity: AnyAnimation<f64>,
1349 child: Option<AnyRenderBox>,
1350 ) -> RenderHandle<Self> {
1351 let this = RenderHandle::new_box(
1352 app,
1353 RenderAnimatedOpacity {
1354 render_object: RenderObjectData::new(),
1355 render_box: RenderBoxData::new(),
1356 child: RenderObjectWithChildData::new(),
1357 animated_opacity: RenderAnimatedOpacityData::new(),
1358 },
1359 );
1360 this.set_child(app, child);
1361 this.set_opacity(app, opacity);
1362 this
1363 }
1364}
1365
1366impl RenderObjectWithChildMixin for RenderAnimatedOpacity {
1367 type ChildType = AnyRenderBox;
1368
1369 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1370 &self.get(app).child
1371 }
1372
1373 fn child_data_mut(
1374 self: RenderHandle<Self>,
1375 app: &mut App,
1376 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1377 &mut self.get_mut(app).child
1378 }
1379}
1380
1381impl RenderProxyBoxMixin for RenderAnimatedOpacity {}
1382
1383impl RenderAnimatedOpacityMixin for RenderAnimatedOpacity {
1384 fn animated_opacity_data(self: RenderHandle<Self>, app: &App) -> &RenderAnimatedOpacityData {
1385 &self.get(app).animated_opacity
1386 }
1387
1388 fn animated_opacity_data_mut(
1389 self: RenderHandle<Self>,
1390 app: &mut App,
1391 ) -> &mut RenderAnimatedOpacityData {
1392 &mut self.get_mut(app).animated_opacity
1393 }
1394}
1395
1396impl RenderObject for RenderAnimatedOpacity {
1397 crate::render_object_accessors!();
1398
1399 fn is_repaint_boundary(self: RenderHandle<Self>, app: &App) -> bool {
1400 RenderAnimatedOpacityMixin::is_repaint_boundary(self, app)
1401 }
1402
1403 fn update_composited_layer(
1404 self: RenderHandle<Self>,
1405 app: &mut App,
1406 old_layer: Option<crate::AnyOffsetLayer>,
1407 ) -> crate::AnyOffsetLayer {
1408 RenderAnimatedOpacityMixin::update_composited_layer(self, app, old_layer)
1409 }
1410
1411 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<crate::PipelineOwner>) {
1412 if let Some(child) = self.child(app) {
1413 child.as_object().attach(app, owner);
1414 }
1415 RenderAnimatedOpacityMixin::did_attach(self, app);
1416 }
1417
1418 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
1419 RenderAnimatedOpacityMixin::did_detach(self, app);
1420 if let Some(child) = self.child(app) {
1421 child.as_object().detach(app);
1422 }
1423 }
1424
1425 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1426 RenderProxyBoxMixin::perform_layout(self, app);
1427 }
1428
1429 fn paint(
1430 self: RenderHandle<Self>,
1431 app: &mut App,
1432 context: &mut PaintingContext,
1433 offset: Offset,
1434 ) {
1435 RenderAnimatedOpacityMixin::paint(self, app, context, offset);
1436 }
1437
1438 fn visit_children(
1439 self: RenderHandle<Self>,
1440 app: &App,
1441 visitor: &mut dyn FnMut(AnyRenderObject),
1442 ) {
1443 if let Some(child) = self.child(app) {
1444 visitor(child.as_object());
1445 }
1446 }
1447}
1448
1449impl RenderBox for RenderAnimatedOpacity {
1450 crate::render_box_accessors!();
1451
1452 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1453 RenderProxyBoxMixin::setup_parent_data(self, app, child);
1454 }
1455
1456 fn apply_paint_transform(
1457 self: RenderHandle<Self>,
1458 app: &App,
1459 child: AnyRenderObject,
1460 transform: &mut Matrix4,
1461 ) {
1462 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
1463 }
1464
1465 fn hit_test_children(
1466 self: RenderHandle<Self>,
1467 app: &mut App,
1468 result: &mut BoxHitTestResult<'_>,
1469 position: Offset,
1470 ) -> bool {
1471 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
1472 }
1473
1474 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1475 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
1476 }
1477
1478 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1479 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
1480 }
1481
1482 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1483 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
1484 }
1485
1486 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1487 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
1488 }
1489
1490 fn compute_distance_to_actual_baseline(
1491 self: RenderHandle<Self>,
1492 app: &mut App,
1493 baseline: TextBaseline,
1494 ) -> Option<f64> {
1495 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
1496 }
1497
1498 fn compute_dry_baseline(
1499 self: RenderHandle<Self>,
1500 app: &mut App,
1501 constraints: BoxConstraints,
1502 baseline: TextBaseline,
1503 ) -> Option<f64> {
1504 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
1505 }
1506
1507 fn compute_dry_layout(
1508 self: RenderHandle<Self>,
1509 app: &mut App,
1510 constraints: BoxConstraints,
1511 ) -> Size {
1512 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
1513 }
1514}
1515
1516pub struct RenderPointerListener {
1528 render_object: RenderObjectData,
1529 render_box: RenderBoxData,
1530 child: RenderObjectWithChildData<AnyRenderBox>,
1531 on_pointer_down: Option<PointerDownEventListener>,
1532 on_pointer_move: Option<PointerMoveEventListener>,
1533 on_pointer_up: Option<PointerUpEventListener>,
1534 on_pointer_hover: Option<PointerHoverEventListener>,
1535 on_pointer_cancel: Option<PointerCancelEventListener>,
1536 on_pointer_pan_zoom_start: Option<PointerPanZoomStartEventListener>,
1537 on_pointer_pan_zoom_update: Option<PointerPanZoomUpdateEventListener>,
1538 on_pointer_pan_zoom_end: Option<PointerPanZoomEndEventListener>,
1539 on_pointer_signal: Option<PointerSignalEventListener>,
1540 behavior: HitTestBehavior,
1541}
1542
1543macro_rules! pointer_listener_field {
1544 ($get:ident, $set:ident, $ty:ty, $doc:expr) => {
1545 #[doc = $doc]
1546 pub fn $get(self: RenderHandle<Self>, app: &App) -> Option<$ty> {
1547 self.get(app).$get.clone()
1548 }
1549
1550 #[doc = concat!("Sets [`", stringify!($get), "`](Self::", stringify!($get), ").")]
1551 pub fn $set(self: RenderHandle<Self>, app: &mut App, value: Option<$ty>) {
1552 self.get_mut(app).$get = value;
1553 }
1554 };
1555}
1556
1557impl RenderPointerListener {
1558 pub fn new(
1563 app: &mut App,
1564 behavior: HitTestBehavior,
1565 child: Option<AnyRenderBox>,
1566 ) -> RenderHandle<Self> {
1567 let this = RenderHandle::new_box(
1568 app,
1569 RenderPointerListener {
1570 render_object: RenderObjectData::new(),
1571 render_box: RenderBoxData::new(),
1572 child: RenderObjectWithChildData::new(),
1573 on_pointer_down: None,
1574 on_pointer_move: None,
1575 on_pointer_up: None,
1576 on_pointer_hover: None,
1577 on_pointer_cancel: None,
1578 on_pointer_pan_zoom_start: None,
1579 on_pointer_pan_zoom_update: None,
1580 on_pointer_pan_zoom_end: None,
1581 on_pointer_signal: None,
1582 behavior,
1583 },
1584 );
1585 this.set_child(app, child);
1586 this
1587 }
1588
1589 pointer_listener_field!(
1590 on_pointer_down,
1591 set_on_pointer_down,
1592 PointerDownEventListener,
1593 "Called when a pointer comes into contact with the screen (for touch pointers), or has its button pressed (for mouse pointers) at this widget's location."
1594 );
1595 pointer_listener_field!(
1596 on_pointer_move,
1597 set_on_pointer_move,
1598 PointerMoveEventListener,
1599 "Called when a pointer that triggered an `on_pointer_down` changes position."
1600 );
1601 pointer_listener_field!(
1602 on_pointer_up,
1603 set_on_pointer_up,
1604 PointerUpEventListener,
1605 "Called when a pointer that triggered an `on_pointer_down` is no longer in contact with the screen."
1606 );
1607 pointer_listener_field!(
1608 on_pointer_hover,
1609 set_on_pointer_hover,
1610 PointerHoverEventListener,
1611 "Called when a pointer that has not an `on_pointer_down` changes position."
1612 );
1613 pointer_listener_field!(
1614 on_pointer_cancel,
1615 set_on_pointer_cancel,
1616 PointerCancelEventListener,
1617 "Called when the input from a pointer that triggered an `on_pointer_down` is no longer directed towards this receiver."
1618 );
1619 pointer_listener_field!(
1620 on_pointer_pan_zoom_start,
1621 set_on_pointer_pan_zoom_start,
1622 PointerPanZoomStartEventListener,
1623 "Called when a pan/zoom begins such as from a trackpad gesture."
1624 );
1625 pointer_listener_field!(
1626 on_pointer_pan_zoom_update,
1627 set_on_pointer_pan_zoom_update,
1628 PointerPanZoomUpdateEventListener,
1629 "Called when a pan/zoom is updated."
1630 );
1631 pointer_listener_field!(
1632 on_pointer_pan_zoom_end,
1633 set_on_pointer_pan_zoom_end,
1634 PointerPanZoomEndEventListener,
1635 "Called when a pan/zoom finishes."
1636 );
1637 pointer_listener_field!(
1638 on_pointer_signal,
1639 set_on_pointer_signal,
1640 PointerSignalEventListener,
1641 "Called when a pointer signal occurs over this object."
1642 );
1643
1644 pub fn set_behavior(self: RenderHandle<Self>, app: &mut App, value: HitTestBehavior) {
1646 self.get_mut(app).behavior = value;
1647 }
1648}
1649
1650impl RenderObjectWithChildMixin for RenderPointerListener {
1651 type ChildType = AnyRenderBox;
1652
1653 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1654 &self.get(app).child
1655 }
1656
1657 fn child_data_mut(
1658 self: RenderHandle<Self>,
1659 app: &mut App,
1660 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1661 &mut self.get_mut(app).child
1662 }
1663}
1664
1665impl RenderProxyBoxMixin for RenderPointerListener {
1666 fn compute_size_for_no_child(
1667 self: RenderHandle<Self>,
1668 _app: &App,
1669 constraints: BoxConstraints,
1670 ) -> Size {
1671 constraints.biggest()
1672 }
1673}
1674
1675impl RenderProxyBoxWithHitTestBehavior for RenderPointerListener {
1676 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
1677 self.get(app).behavior
1678 }
1679}
1680
1681impl RenderObject for RenderPointerListener {
1682 crate::render_object_accessors!();
1683
1684 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
1685 RenderProxyBoxMixin::perform_layout(self, app);
1686 }
1687
1688 fn paint(
1689 self: RenderHandle<Self>,
1690 app: &mut App,
1691 context: &mut PaintingContext,
1692 offset: Offset,
1693 ) {
1694 RenderProxyBoxMixin::paint(self, app, context, offset);
1695 }
1696
1697 fn visit_children(
1698 self: RenderHandle<Self>,
1699 app: &App,
1700 visitor: &mut dyn FnMut(AnyRenderObject),
1701 ) {
1702 if let Some(child) = self.child(app) {
1703 visitor(child.as_object());
1704 }
1705 }
1706}
1707
1708impl RenderBox for RenderPointerListener {
1709 crate::render_box_accessors!();
1710
1711 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
1712 RenderProxyBoxMixin::setup_parent_data(self, app, child);
1713 }
1714
1715 fn apply_paint_transform(
1716 self: RenderHandle<Self>,
1717 app: &App,
1718 child: AnyRenderObject,
1719 transform: &mut Matrix4,
1720 ) {
1721 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
1722 }
1723
1724 fn handle_event(
1725 self: RenderHandle<Self>,
1726 app: &mut App,
1727 event: &PointerEvent,
1728 _entry: &BoxHitTestEntry,
1729 ) {
1730 match event {
1731 PointerEvent::Down(event) => {
1732 if let Some(callback) = self.get(app).on_pointer_down.clone() {
1733 callback(app, event.clone());
1734 }
1735 }
1736 PointerEvent::Move(event) => {
1737 if let Some(callback) = self.get(app).on_pointer_move.clone() {
1738 callback(app, event.clone());
1739 }
1740 }
1741 PointerEvent::Up(event) => {
1742 if let Some(callback) = self.get(app).on_pointer_up.clone() {
1743 callback(app, event.clone());
1744 }
1745 }
1746 PointerEvent::Hover(event) => {
1747 if let Some(callback) = self.get(app).on_pointer_hover.clone() {
1748 callback(app, event.clone());
1749 }
1750 }
1751 PointerEvent::Cancel(event) => {
1752 if let Some(callback) = self.get(app).on_pointer_cancel.clone() {
1753 callback(app, event.clone());
1754 }
1755 }
1756 PointerEvent::PanZoomStart(event) => {
1757 if let Some(callback) = self.get(app).on_pointer_pan_zoom_start.clone() {
1758 callback(app, event.clone());
1759 }
1760 }
1761 PointerEvent::PanZoomUpdate(event) => {
1762 if let Some(callback) = self.get(app).on_pointer_pan_zoom_update.clone() {
1763 callback(app, event.clone());
1764 }
1765 }
1766 PointerEvent::PanZoomEnd(event) => {
1767 if let Some(callback) = self.get(app).on_pointer_pan_zoom_end.clone() {
1768 callback(app, event.clone());
1769 }
1770 }
1771 PointerEvent::Scroll(_)
1772 | PointerEvent::ScrollInertiaCancel(_)
1773 | PointerEvent::Scale(_) => {
1774 if let Some(callback) = self.get(app).on_pointer_signal.clone() {
1775 callback(app, event.clone());
1776 }
1777 }
1778 PointerEvent::Added(_)
1779 | PointerEvent::Removed(_)
1780 | PointerEvent::Enter(_)
1781 | PointerEvent::Exit(_) => {}
1782 }
1783 }
1784
1785 fn hit_test(
1786 self: RenderHandle<Self>,
1787 app: &mut App,
1788 result: &mut BoxHitTestResult<'_>,
1789 position: Offset,
1790 ) -> bool {
1791 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
1792 }
1793
1794 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
1795 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
1796 }
1797
1798 fn hit_test_children(
1799 self: RenderHandle<Self>,
1800 app: &mut App,
1801 result: &mut BoxHitTestResult<'_>,
1802 position: Offset,
1803 ) -> bool {
1804 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
1805 }
1806
1807 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1808 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
1809 }
1810
1811 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
1812 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
1813 }
1814
1815 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1816 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
1817 }
1818
1819 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
1820 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
1821 }
1822
1823 fn compute_distance_to_actual_baseline(
1824 self: RenderHandle<Self>,
1825 app: &mut App,
1826 baseline: TextBaseline,
1827 ) -> Option<f64> {
1828 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
1829 }
1830
1831 fn compute_dry_baseline(
1832 self: RenderHandle<Self>,
1833 app: &mut App,
1834 constraints: BoxConstraints,
1835 baseline: TextBaseline,
1836 ) -> Option<f64> {
1837 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
1838 }
1839
1840 fn compute_dry_layout(
1841 self: RenderHandle<Self>,
1842 app: &mut App,
1843 constraints: BoxConstraints,
1844 ) -> Size {
1845 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
1846 }
1847}
1848
1849#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1851pub enum DecorationPosition {
1852 Background,
1854
1855 Foreground,
1857}
1858
1859pub struct RenderDecoratedBox {
1861 render_object: RenderObjectData,
1862 render_box: RenderBoxData,
1863 child: RenderObjectWithChildData<AnyRenderBox>,
1864 painter: Option<Box<dyn BoxPainter>>,
1865 decoration: Box<dyn Decoration>,
1866 position: DecorationPosition,
1867 configuration: ImageConfiguration,
1868}
1869
1870impl RenderDecoratedBox {
1871 pub fn new(
1875 app: &mut App,
1876 decoration: Box<dyn Decoration>,
1877 position: DecorationPosition,
1878 configuration: ImageConfiguration,
1879 child: Option<AnyRenderBox>,
1880 ) -> RenderHandle<Self> {
1881 let this = RenderHandle::new_box(
1882 app,
1883 RenderDecoratedBox {
1884 render_object: RenderObjectData::new(),
1885 render_box: RenderBoxData::new(),
1886 child: RenderObjectWithChildData::new(),
1887 painter: None,
1888 decoration,
1889 position,
1890 configuration,
1891 },
1892 );
1893 this.set_child(app, child);
1894 this
1895 }
1896
1897 pub fn decoration(self: RenderHandle<Self>, app: &App) -> &dyn Decoration {
1899 &*self.get(app).decoration
1900 }
1901
1902 pub fn set_decoration(self: RenderHandle<Self>, app: &mut App, value: Box<dyn Decoration>) {
1904 if value.eq_decoration(&*self.get(app).decoration) {
1905 return;
1906 }
1907 let this = self.get_mut(app);
1908 if let Some(mut painter) = this.painter.take() {
1909 painter.dispose();
1910 }
1911 this.decoration = value;
1912 self.mark_needs_paint(app);
1913 }
1914
1915 pub fn position(self: RenderHandle<Self>, app: &App) -> DecorationPosition {
1917 self.get(app).position
1918 }
1919
1920 pub fn set_position(self: RenderHandle<Self>, app: &mut App, value: DecorationPosition) {
1922 if self.get(app).position == value {
1923 return;
1924 }
1925 self.get_mut(app).position = value;
1926 self.mark_needs_paint(app);
1927 }
1928
1929 pub fn configuration(self: RenderHandle<Self>, app: &App) -> &ImageConfiguration {
1932 &self.get(app).configuration
1933 }
1934
1935 pub fn set_configuration(self: RenderHandle<Self>, app: &mut App, value: ImageConfiguration) {
1937 if self.get(app).configuration == value {
1938 return;
1939 }
1940 self.get_mut(app).configuration = value;
1941 self.mark_needs_paint(app);
1942 }
1943
1944 fn paint_decoration(
1945 self: RenderHandle<Self>,
1946 app: &mut App,
1947 context: &mut PaintingContext,
1948 offset: Offset,
1949 configuration: &ImageConfiguration,
1950 ) {
1951 let debug_save_count = context.canvas().save_count();
1952 let is_complex = {
1953 let this = self.get_mut(app);
1954 let painter = this
1955 .painter
1956 .get_or_insert_with(|| this.decoration.create_box_painter(None));
1957 painter.paint(context.canvas(), offset, configuration);
1958 this.decoration.is_complex()
1959 };
1960 debug_assert_eq!(
1961 debug_save_count,
1962 context.canvas().save_count(),
1963 "the decoration's painter had mismatching save and restore calls"
1964 );
1965 if is_complex {
1966 context.set_is_complex_hint();
1967 }
1968 }
1969}
1970
1971impl RenderObjectWithChildMixin for RenderDecoratedBox {
1972 type ChildType = AnyRenderBox;
1973
1974 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1975 &self.get(app).child
1976 }
1977
1978 fn child_data_mut(
1979 self: RenderHandle<Self>,
1980 app: &mut App,
1981 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1982 &mut self.get_mut(app).child
1983 }
1984}
1985
1986impl RenderProxyBoxMixin for RenderDecoratedBox {}
1987
1988impl RenderObject for RenderDecoratedBox {
1989 crate::render_object_accessors!();
1990
1991 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
1992 if let Some(mut painter) = self.get_mut(app).painter.take() {
1993 painter.dispose();
1994 }
1995 if let Some(child) = self.child(app) {
1996 child.as_object().detach(app);
1997 }
1998 self.mark_needs_paint(app);
1999 }
2000
2001 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2002 RenderProxyBoxMixin::perform_layout(self, app);
2003 }
2004
2005 fn paint(
2006 self: RenderHandle<Self>,
2007 app: &mut App,
2008 context: &mut PaintingContext,
2009 offset: Offset,
2010 ) {
2011 let size = self.size(app);
2012 let filled_configuration =
2013 self.get(app)
2014 .configuration
2015 .copy_with(None, None, None, None, Some(size), None);
2016 if self.get(app).position == DecorationPosition::Background {
2017 self.paint_decoration(app, context, offset, &filled_configuration);
2018 }
2019 RenderProxyBoxMixin::paint(self, app, context, offset);
2020 if self.get(app).position == DecorationPosition::Foreground {
2021 self.paint_decoration(app, context, offset, &filled_configuration);
2022 }
2023 }
2024
2025 fn visit_children(
2026 self: RenderHandle<Self>,
2027 app: &App,
2028 visitor: &mut dyn FnMut(AnyRenderObject),
2029 ) {
2030 if let Some(child) = self.child(app) {
2031 visitor(child.as_object());
2032 }
2033 }
2034}
2035
2036impl RenderBox for RenderDecoratedBox {
2037 crate::render_box_accessors!();
2038
2039 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
2040 let this = self.get(app);
2041 this.decoration
2042 .hit_test(self.size(app), position, this.configuration.text_direction)
2043 }
2044
2045 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2046 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2047 }
2048
2049 fn apply_paint_transform(
2050 self: RenderHandle<Self>,
2051 app: &App,
2052 child: AnyRenderObject,
2053 transform: &mut Matrix4,
2054 ) {
2055 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2056 }
2057
2058 fn hit_test_children(
2059 self: RenderHandle<Self>,
2060 app: &mut App,
2061 result: &mut BoxHitTestResult<'_>,
2062 position: Offset,
2063 ) -> bool {
2064 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2065 }
2066
2067 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2068 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2069 }
2070
2071 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2072 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2073 }
2074
2075 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2076 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2077 }
2078
2079 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2080 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2081 }
2082
2083 fn compute_distance_to_actual_baseline(
2084 self: RenderHandle<Self>,
2085 app: &mut App,
2086 baseline: TextBaseline,
2087 ) -> Option<f64> {
2088 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2089 }
2090
2091 fn compute_dry_baseline(
2092 self: RenderHandle<Self>,
2093 app: &mut App,
2094 constraints: BoxConstraints,
2095 baseline: TextBaseline,
2096 ) -> Option<f64> {
2097 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2098 }
2099
2100 fn compute_dry_layout(
2101 self: RenderHandle<Self>,
2102 app: &mut App,
2103 constraints: BoxConstraints,
2104 ) -> Size {
2105 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2106 }
2107}
2108
2109pub struct RenderRepaintBoundary {
2115 render_object: RenderObjectData,
2116 render_box: RenderBoxData,
2117 child: RenderObjectWithChildData<AnyRenderBox>,
2118}
2119
2120impl RenderRepaintBoundary {
2121 pub fn new(app: &mut App, child: Option<AnyRenderBox>) -> RenderHandle<Self> {
2123 let this = RenderHandle::new_box(
2124 app,
2125 RenderRepaintBoundary {
2126 render_object: RenderObjectData::new(),
2127 render_box: RenderBoxData::new(),
2128 child: RenderObjectWithChildData::new(),
2129 },
2130 );
2131 this.set_child(app, child);
2132 this
2133 }
2134}
2135
2136impl RenderObjectWithChildMixin for RenderRepaintBoundary {
2137 type ChildType = AnyRenderBox;
2138
2139 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2140 &self.get(app).child
2141 }
2142
2143 fn child_data_mut(
2144 self: RenderHandle<Self>,
2145 app: &mut App,
2146 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2147 &mut self.get_mut(app).child
2148 }
2149}
2150
2151impl RenderProxyBoxMixin for RenderRepaintBoundary {}
2152
2153impl RenderObject for RenderRepaintBoundary {
2154 crate::render_object_accessors!();
2155
2156 fn is_repaint_boundary(self: RenderHandle<Self>, _app: &App) -> bool {
2157 true
2158 }
2159
2160 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2161 RenderProxyBoxMixin::perform_layout(self, app);
2162 }
2163
2164 fn paint(
2165 self: RenderHandle<Self>,
2166 app: &mut App,
2167 context: &mut PaintingContext,
2168 offset: Offset,
2169 ) {
2170 RenderProxyBoxMixin::paint(self, app, context, offset);
2171 }
2172
2173 fn visit_children(
2174 self: RenderHandle<Self>,
2175 app: &App,
2176 visitor: &mut dyn FnMut(AnyRenderObject),
2177 ) {
2178 if let Some(child) = self.child(app) {
2179 visitor(child.as_object());
2180 }
2181 }
2182}
2183
2184impl RenderBox for RenderRepaintBoundary {
2185 crate::render_box_accessors!();
2186
2187 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2188 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2189 }
2190
2191 fn apply_paint_transform(
2192 self: RenderHandle<Self>,
2193 app: &App,
2194 child: AnyRenderObject,
2195 transform: &mut Matrix4,
2196 ) {
2197 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2198 }
2199
2200 fn hit_test_children(
2201 self: RenderHandle<Self>,
2202 app: &mut App,
2203 result: &mut BoxHitTestResult<'_>,
2204 position: Offset,
2205 ) -> bool {
2206 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2207 }
2208
2209 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2210 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2211 }
2212
2213 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2214 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2215 }
2216
2217 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2218 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2219 }
2220
2221 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2222 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2223 }
2224
2225 fn compute_distance_to_actual_baseline(
2226 self: RenderHandle<Self>,
2227 app: &mut App,
2228 baseline: TextBaseline,
2229 ) -> Option<f64> {
2230 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2231 }
2232
2233 fn compute_dry_baseline(
2234 self: RenderHandle<Self>,
2235 app: &mut App,
2236 constraints: BoxConstraints,
2237 baseline: TextBaseline,
2238 ) -> Option<f64> {
2239 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2240 }
2241
2242 fn compute_dry_layout(
2243 self: RenderHandle<Self>,
2244 app: &mut App,
2245 constraints: BoxConstraints,
2246 ) -> Size {
2247 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2248 }
2249}
2250
2251pub struct RenderMouseRegion {
2273 render_object: RenderObjectData,
2274 render_box: RenderBoxData,
2275 child: RenderObjectWithChildData<AnyRenderBox>,
2276 on_enter: Option<PointerEnterEventListener>,
2277 on_hover: Option<PointerHoverEventListener>,
2278 on_exit: Option<PointerExitEventListener>,
2279 cursor: MouseCursorRef,
2280 valid_for_mouse_tracker: bool,
2281 opaque: bool,
2282 behavior: HitTestBehavior,
2283}
2284
2285impl RenderMouseRegion {
2286 pub fn new(
2292 app: &mut App,
2293 valid_for_mouse_tracker: bool,
2294 child: Option<AnyRenderBox>,
2295 ) -> RenderHandle<Self> {
2296 let this = RenderHandle::new_box(
2297 app,
2298 RenderMouseRegion {
2299 render_object: RenderObjectData::new(),
2300 render_box: RenderBoxData::new(),
2301 child: RenderObjectWithChildData::new(),
2302 on_enter: None,
2303 on_hover: None,
2304 on_exit: None,
2305 cursor: <dyn MouseCursor>::defer(),
2306 valid_for_mouse_tracker,
2307 opaque: true,
2308 behavior: HitTestBehavior::Opaque,
2309 },
2310 );
2311 this.set_child(app, child);
2312 this
2313 }
2314
2315 pub fn opaque(self: RenderHandle<Self>, app: &App) -> bool {
2330 self.get(app).opaque
2331 }
2332
2333 pub fn set_opaque(self: RenderHandle<Self>, app: &mut App, value: bool) {
2335 if self.get(app).opaque != value {
2336 self.get_mut(app).opaque = value;
2337 self.mark_needs_paint(app);
2339 }
2340 }
2341
2342 pub fn hit_test_behavior(self: RenderHandle<Self>, app: &App) -> Option<HitTestBehavior> {
2346 Some(self.get(app).behavior)
2347 }
2348
2349 pub fn set_hit_test_behavior(
2351 self: RenderHandle<Self>,
2352 app: &mut App,
2353 value: Option<HitTestBehavior>,
2354 ) {
2355 let new_value = value.unwrap_or(HitTestBehavior::Opaque);
2356 if self.get(app).behavior != new_value {
2357 self.get_mut(app).behavior = new_value;
2358 self.mark_needs_paint(app);
2360 }
2361 }
2362
2363 pointer_listener_field!(
2364 on_enter,
2365 set_on_enter,
2366 PointerEnterEventListener,
2367 "Triggered when a mouse pointer, with or without buttons pressed, has entered the region and `valid_for_mouse_tracker` is true."
2368 );
2369 pointer_listener_field!(
2370 on_hover,
2371 set_on_hover,
2372 PointerHoverEventListener,
2373 "Triggered when a pointer has moved onto or within the region without buttons pressed."
2374 );
2375 pointer_listener_field!(
2376 on_exit,
2377 set_on_exit,
2378 PointerExitEventListener,
2379 "Triggered when a mouse pointer, with or without buttons pressed, has exited the region and `valid_for_mouse_tracker` is true."
2380 );
2381
2382 pub fn cursor(self: RenderHandle<Self>, app: &App) -> MouseCursorRef {
2391 Rc::clone(&self.get(app).cursor)
2392 }
2393
2394 pub fn set_cursor(self: RenderHandle<Self>, app: &mut App, value: MouseCursorRef) {
2396 if *self.get(app).cursor != *value {
2397 self.get_mut(app).cursor = value;
2398 self.mark_needs_paint(app);
2401 }
2402 }
2403
2404 pub fn valid_for_mouse_tracker(self: RenderHandle<Self>, app: &App) -> bool {
2407 self.get(app).valid_for_mouse_tracker
2408 }
2409}
2410
2411impl RenderObjectWithChildMixin for RenderMouseRegion {
2412 type ChildType = AnyRenderBox;
2413
2414 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2415 &self.get(app).child
2416 }
2417
2418 fn child_data_mut(
2419 self: RenderHandle<Self>,
2420 app: &mut App,
2421 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2422 &mut self.get_mut(app).child
2423 }
2424}
2425
2426impl RenderProxyBoxMixin for RenderMouseRegion {
2427 fn compute_size_for_no_child(
2428 self: RenderHandle<Self>,
2429 _app: &App,
2430 constraints: BoxConstraints,
2431 ) -> Size {
2432 constraints.biggest()
2433 }
2434}
2435
2436impl RenderProxyBoxWithHitTestBehavior for RenderMouseRegion {
2437 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
2438 self.get(app).behavior
2439 }
2440}
2441
2442impl RenderObject for RenderMouseRegion {
2443 crate::render_object_accessors!();
2444
2445 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
2446 for child in [self.child(app)].into_iter().flatten() {
2447 child.as_object().attach(app, owner);
2448 }
2449 self.get_mut(app).valid_for_mouse_tracker = true;
2450 }
2451
2452 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
2453 self.get_mut(app).valid_for_mouse_tracker = false;
2455 for child in [self.child(app)].into_iter().flatten() {
2456 child.as_object().detach(app);
2457 }
2458 }
2459
2460 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2461 RenderProxyBoxMixin::perform_layout(self, app);
2462 }
2463
2464 fn mouse_tracker_annotation(
2465 self: RenderHandle<Self>,
2466 app: &App,
2467 ) -> Option<MouseTrackerAnnotation> {
2468 let this = self.get(app);
2469 Some(MouseTrackerAnnotation {
2470 on_enter: this.on_enter.clone(),
2471 on_exit: this.on_exit.clone(),
2472 cursor: Rc::clone(&this.cursor),
2473 valid_for_mouse_tracker: this.valid_for_mouse_tracker,
2474 })
2475 }
2476
2477 fn paint(
2478 self: RenderHandle<Self>,
2479 app: &mut App,
2480 context: &mut PaintingContext,
2481 offset: Offset,
2482 ) {
2483 RenderProxyBoxMixin::paint(self, app, context, offset);
2484 }
2485
2486 fn visit_children(
2487 self: RenderHandle<Self>,
2488 app: &App,
2489 visitor: &mut dyn FnMut(AnyRenderObject),
2490 ) {
2491 if let Some(child) = self.child(app) {
2492 visitor(child.as_object());
2493 }
2494 }
2495}
2496
2497impl RenderBox for RenderMouseRegion {
2498 crate::render_box_accessors!();
2499
2500 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2501 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2502 }
2503
2504 fn apply_paint_transform(
2505 self: RenderHandle<Self>,
2506 app: &App,
2507 child: AnyRenderObject,
2508 transform: &mut Matrix4,
2509 ) {
2510 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2511 }
2512
2513 fn hit_test(
2514 self: RenderHandle<Self>,
2515 app: &mut App,
2516 result: &mut BoxHitTestResult<'_>,
2517 position: Offset,
2518 ) -> bool {
2519 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
2520 && self.get(app).opaque
2521 }
2522
2523 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
2524 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
2525 }
2526
2527 fn hit_test_children(
2528 self: RenderHandle<Self>,
2529 app: &mut App,
2530 result: &mut BoxHitTestResult<'_>,
2531 position: Offset,
2532 ) -> bool {
2533 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2534 }
2535
2536 fn handle_event(
2537 self: RenderHandle<Self>,
2538 app: &mut App,
2539 event: &PointerEvent,
2540 _entry: &BoxHitTestEntry,
2541 ) {
2542 if let PointerEvent::Hover(event) = event
2543 && let Some(on_hover) = self.get(app).on_hover.clone()
2544 {
2545 on_hover(app, event.clone());
2546 }
2547 }
2548
2549 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2550 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2551 }
2552
2553 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2554 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2555 }
2556
2557 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2558 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2559 }
2560
2561 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2562 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2563 }
2564
2565 fn compute_distance_to_actual_baseline(
2566 self: RenderHandle<Self>,
2567 app: &mut App,
2568 baseline: TextBaseline,
2569 ) -> Option<f64> {
2570 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2571 }
2572
2573 fn compute_dry_baseline(
2574 self: RenderHandle<Self>,
2575 app: &mut App,
2576 constraints: BoxConstraints,
2577 baseline: TextBaseline,
2578 ) -> Option<f64> {
2579 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2580 }
2581
2582 fn compute_dry_layout(
2583 self: RenderHandle<Self>,
2584 app: &mut App,
2585 constraints: BoxConstraints,
2586 ) -> Size {
2587 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2588 }
2589}
2590
2591pub(crate) fn same_instance<T: ?Sized>(a: Option<&Rc<T>>, b: Option<&Rc<T>>) -> bool {
2593 match (a, b) {
2594 (None, None) => true,
2595 (Some(a), Some(b)) => Rc::ptr_eq(a, b),
2596 _ => false,
2597 }
2598}
2599
2600pub struct RenderLimitedBox {
2613 render_object: RenderObjectData,
2614 render_box: RenderBoxData,
2615 child: RenderObjectWithChildData<AnyRenderBox>,
2616 max_width: f64,
2617 max_height: f64,
2618}
2619
2620impl RenderLimitedBox {
2621 pub fn new(
2626 app: &mut App,
2627 max_width: f64,
2628 max_height: f64,
2629 child: Option<AnyRenderBox>,
2630 ) -> RenderHandle<RenderLimitedBox> {
2631 debug_assert!(max_width >= 0.0);
2632 debug_assert!(max_height >= 0.0);
2633 let this = RenderHandle::new_box(
2634 app,
2635 RenderLimitedBox {
2636 render_object: RenderObjectData::new(),
2637 render_box: RenderBoxData::new(),
2638 child: RenderObjectWithChildData::new(),
2639 max_width,
2640 max_height,
2641 },
2642 );
2643 this.set_child(app, child);
2644 this
2645 }
2646
2647 pub fn max_width(self: RenderHandle<Self>, app: &App) -> f64 {
2649 self.get(app).max_width
2650 }
2651
2652 pub fn set_max_width(self: RenderHandle<Self>, app: &mut App, value: f64) {
2654 debug_assert!(value >= 0.0);
2655 if self.get(app).max_width == value {
2656 return;
2657 }
2658 self.get_mut(app).max_width = value;
2659 self.mark_needs_layout(app);
2660 }
2661
2662 pub fn max_height(self: RenderHandle<Self>, app: &App) -> f64 {
2664 self.get(app).max_height
2665 }
2666
2667 pub fn set_max_height(self: RenderHandle<Self>, app: &mut App, value: f64) {
2669 debug_assert!(value >= 0.0);
2670 if self.get(app).max_height == value {
2671 return;
2672 }
2673 self.get_mut(app).max_height = value;
2674 self.mark_needs_layout(app);
2675 }
2676
2677 fn compute_size(
2679 self: RenderHandle<Self>,
2680 app: &mut App,
2681 constraints: BoxConstraints,
2682 layout_child: ChildLayouter,
2683 ) -> Size {
2684 let limited = self.limit_constraints(app, constraints);
2685 match self.child(app) {
2686 Some(child) => constraints.constrain(layout_child(app, child, limited)),
2687 None => limited.constrain(Size::ZERO),
2688 }
2689 }
2690
2691 fn limit_constraints(
2692 self: RenderHandle<Self>,
2693 app: &App,
2694 constraints: BoxConstraints,
2695 ) -> BoxConstraints {
2696 let this = self.get(app);
2697 BoxConstraints::new()
2698 .min_width(constraints.min_width)
2699 .max_width(if constraints.has_bounded_width() {
2700 constraints.max_width
2701 } else {
2702 constraints.constrain_width(this.max_width)
2703 })
2704 .min_height(constraints.min_height)
2705 .max_height(if constraints.has_bounded_height() {
2706 constraints.max_height
2707 } else {
2708 constraints.constrain_height(this.max_height)
2709 })
2710 }
2711}
2712
2713impl RenderObjectWithChildMixin for RenderLimitedBox {
2714 type ChildType = AnyRenderBox;
2715
2716 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2717 &self.get(app).child
2718 }
2719
2720 fn child_data_mut(
2721 self: RenderHandle<Self>,
2722 app: &mut App,
2723 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2724 &mut self.get_mut(app).child
2725 }
2726}
2727
2728impl RenderProxyBoxMixin for RenderLimitedBox {}
2729
2730impl RenderObject for RenderLimitedBox {
2731 crate::render_object_accessors!();
2732
2733 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2734 let constraints = self.constraints(app);
2735 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
2736 self.set_size(app, size);
2737 }
2738
2739 fn paint(
2740 self: RenderHandle<Self>,
2741 app: &mut App,
2742 context: &mut PaintingContext,
2743 offset: Offset,
2744 ) {
2745 RenderProxyBoxMixin::paint(self, app, context, offset);
2746 }
2747
2748 fn visit_children(
2749 self: RenderHandle<Self>,
2750 app: &App,
2751 visitor: &mut dyn FnMut(AnyRenderObject),
2752 ) {
2753 if let Some(child) = self.child(app) {
2754 visitor(child.as_object());
2755 }
2756 }
2757}
2758
2759impl RenderBox for RenderLimitedBox {
2760 crate::render_box_accessors!();
2761
2762 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2763 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2764 }
2765
2766 fn apply_paint_transform(
2767 self: RenderHandle<Self>,
2768 app: &App,
2769 child: AnyRenderObject,
2770 transform: &mut Matrix4,
2771 ) {
2772 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2773 }
2774
2775 fn hit_test_children(
2776 self: RenderHandle<Self>,
2777 app: &mut App,
2778 result: &mut BoxHitTestResult<'_>,
2779 position: Offset,
2780 ) -> bool {
2781 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2782 }
2783
2784 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2785 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2786 }
2787
2788 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2789 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2790 }
2791
2792 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2793 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2794 }
2795
2796 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2797 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2798 }
2799
2800 fn compute_distance_to_actual_baseline(
2801 self: RenderHandle<Self>,
2802 app: &mut App,
2803 baseline: TextBaseline,
2804 ) -> Option<f64> {
2805 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2806 }
2807
2808 fn compute_dry_baseline(
2809 self: RenderHandle<Self>,
2810 app: &mut App,
2811 constraints: BoxConstraints,
2812 baseline: TextBaseline,
2813 ) -> Option<f64> {
2814 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2815 }
2816
2817 fn compute_dry_layout(
2818 self: RenderHandle<Self>,
2819 app: &mut App,
2820 constraints: BoxConstraints,
2821 ) -> Size {
2822 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
2823 }
2824}
2825
2826pub struct RenderAspectRatio {
2840 render_object: RenderObjectData,
2841 render_box: RenderBoxData,
2842 child: RenderObjectWithChildData<AnyRenderBox>,
2843 aspect_ratio: f64,
2844}
2845
2846impl RenderAspectRatio {
2847 pub fn new(
2851 app: &mut App,
2852 aspect_ratio: f64,
2853 child: Option<AnyRenderBox>,
2854 ) -> RenderHandle<RenderAspectRatio> {
2855 debug_assert!(aspect_ratio > 0.0);
2856 debug_assert!(aspect_ratio.is_finite());
2857 let this = RenderHandle::new_box(
2858 app,
2859 RenderAspectRatio {
2860 render_object: RenderObjectData::new(),
2861 render_box: RenderBoxData::new(),
2862 child: RenderObjectWithChildData::new(),
2863 aspect_ratio,
2864 },
2865 );
2866 this.set_child(app, child);
2867 this
2868 }
2869
2870 pub fn aspect_ratio(self: RenderHandle<Self>, app: &App) -> f64 {
2875 self.get(app).aspect_ratio
2876 }
2877
2878 pub fn set_aspect_ratio(self: RenderHandle<Self>, app: &mut App, value: f64) {
2880 debug_assert!(value > 0.0);
2881 debug_assert!(value.is_finite());
2882 if self.get(app).aspect_ratio == value {
2883 return;
2884 }
2885 self.get_mut(app).aspect_ratio = value;
2886 self.mark_needs_layout(app);
2887 }
2888
2889 fn apply_aspect_ratio(
2890 self: RenderHandle<Self>,
2891 app: &App,
2892 constraints: BoxConstraints,
2893 ) -> Size {
2894 debug_assert!(constraints.debug_assert_is_valid(false));
2895 let aspect_ratio = self.get(app).aspect_ratio;
2896 debug_assert!(
2897 constraints.has_bounded_width() || constraints.has_bounded_height(),
2898 "{} has unbounded constraints.\n\
2899 This render object was given an aspect ratio of {aspect_ratio} but was given both \
2900 unbounded width and unbounded height constraints. Because both constraints were \
2901 unbounded, this render object doesn't know how much size to consume.",
2902 std::any::type_name::<Self>()
2903 );
2904
2905 if constraints.is_tight() {
2906 return constraints.smallest();
2907 }
2908
2909 let mut width = constraints.max_width;
2910 let mut height;
2911
2912 if width.is_finite() {
2915 height = width / aspect_ratio;
2916 } else {
2917 height = constraints.max_height;
2918 width = height * aspect_ratio;
2919 }
2920
2921 if width > constraints.max_width {
2926 width = constraints.max_width;
2927 height = width / aspect_ratio;
2928 }
2929
2930 if height > constraints.max_height {
2931 height = constraints.max_height;
2932 width = height * aspect_ratio;
2933 }
2934
2935 if width < constraints.min_width {
2936 width = constraints.min_width;
2937 height = width / aspect_ratio;
2938 }
2939
2940 if height < constraints.min_height {
2941 height = constraints.min_height;
2942 width = height * aspect_ratio;
2943 }
2944
2945 constraints.constrain(Size::new(width, height))
2946 }
2947}
2948
2949impl RenderObjectWithChildMixin for RenderAspectRatio {
2950 type ChildType = AnyRenderBox;
2951
2952 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2953 &self.get(app).child
2954 }
2955
2956 fn child_data_mut(
2957 self: RenderHandle<Self>,
2958 app: &mut App,
2959 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2960 &mut self.get_mut(app).child
2961 }
2962}
2963
2964impl RenderProxyBoxMixin for RenderAspectRatio {}
2965
2966impl RenderObject for RenderAspectRatio {
2967 crate::render_object_accessors!();
2968
2969 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2970 let constraints = self.constraints(app);
2971 let size = self.get_dry_layout(app, constraints);
2972 self.set_size(app, size);
2973 if let Some(child) = self.child(app) {
2974 child.layout(app, BoxConstraints::tight(size), false);
2975 }
2976 }
2977
2978 fn paint(
2979 self: RenderHandle<Self>,
2980 app: &mut App,
2981 context: &mut PaintingContext,
2982 offset: Offset,
2983 ) {
2984 RenderProxyBoxMixin::paint(self, app, context, offset);
2985 }
2986
2987 fn visit_children(
2988 self: RenderHandle<Self>,
2989 app: &App,
2990 visitor: &mut dyn FnMut(AnyRenderObject),
2991 ) {
2992 if let Some(child) = self.child(app) {
2993 visitor(child.as_object());
2994 }
2995 }
2996}
2997
2998impl RenderBox for RenderAspectRatio {
2999 crate::render_box_accessors!();
3000
3001 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3002 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3003 }
3004
3005 fn apply_paint_transform(
3006 self: RenderHandle<Self>,
3007 app: &App,
3008 child: AnyRenderObject,
3009 transform: &mut Matrix4,
3010 ) {
3011 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3012 }
3013
3014 fn hit_test_children(
3015 self: RenderHandle<Self>,
3016 app: &mut App,
3017 result: &mut BoxHitTestResult<'_>,
3018 position: Offset,
3019 ) -> bool {
3020 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3021 }
3022
3023 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3024 if height.is_finite() {
3025 return height * self.get(app).aspect_ratio;
3026 }
3027 match self.child(app) {
3028 Some(child) => child.get_min_intrinsic_width(app, height),
3029 None => 0.0,
3030 }
3031 }
3032
3033 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3034 if height.is_finite() {
3035 return height * self.get(app).aspect_ratio;
3036 }
3037 match self.child(app) {
3038 Some(child) => child.get_max_intrinsic_width(app, height),
3039 None => 0.0,
3040 }
3041 }
3042
3043 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3044 if width.is_finite() {
3045 return width / self.get(app).aspect_ratio;
3046 }
3047 match self.child(app) {
3048 Some(child) => child.get_min_intrinsic_height(app, width),
3049 None => 0.0,
3050 }
3051 }
3052
3053 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3054 if width.is_finite() {
3055 return width / self.get(app).aspect_ratio;
3056 }
3057 match self.child(app) {
3058 Some(child) => child.get_max_intrinsic_height(app, width),
3059 None => 0.0,
3060 }
3061 }
3062
3063 fn compute_distance_to_actual_baseline(
3064 self: RenderHandle<Self>,
3065 app: &mut App,
3066 baseline: TextBaseline,
3067 ) -> Option<f64> {
3068 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3069 }
3070
3071 fn compute_dry_layout(
3072 self: RenderHandle<Self>,
3073 app: &mut App,
3074 constraints: BoxConstraints,
3075 ) -> Size {
3076 self.apply_aspect_ratio(app, constraints)
3077 }
3078
3079 fn compute_dry_baseline(
3080 self: RenderHandle<Self>,
3081 app: &mut App,
3082 constraints: BoxConstraints,
3083 baseline: TextBaseline,
3084 ) -> Option<f64> {
3085 let size = self.get_dry_layout(app, constraints);
3086 RenderProxyBoxMixin::compute_dry_baseline(self, app, BoxConstraints::tight(size), baseline)
3087 }
3088}
3089
3090pub struct RenderIntrinsicWidth {
3110 render_object: RenderObjectData,
3111 render_box: RenderBoxData,
3112 child: RenderObjectWithChildData<AnyRenderBox>,
3113 step_width: Option<f64>,
3114 step_height: Option<f64>,
3115}
3116
3117fn apply_step(input: f64, step: Option<f64>) -> f64 {
3119 debug_assert!(input.is_finite());
3120 match step {
3121 Some(step) => (input / step).ceil() * step,
3122 None => input,
3123 }
3124}
3125
3126impl RenderIntrinsicWidth {
3127 pub fn new(
3132 app: &mut App,
3133 step_width: Option<f64>,
3134 step_height: Option<f64>,
3135 child: Option<AnyRenderBox>,
3136 ) -> RenderHandle<RenderIntrinsicWidth> {
3137 debug_assert!(step_width.is_none_or(|step| step > 0.0));
3138 debug_assert!(step_height.is_none_or(|step| step > 0.0));
3139 let this = RenderHandle::new_box(
3140 app,
3141 RenderIntrinsicWidth {
3142 render_object: RenderObjectData::new(),
3143 render_box: RenderBoxData::new(),
3144 child: RenderObjectWithChildData::new(),
3145 step_width,
3146 step_height,
3147 },
3148 );
3149 this.set_child(app, child);
3150 this
3151 }
3152
3153 pub fn step_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
3155 self.get(app).step_width
3156 }
3157
3158 pub fn set_step_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
3160 debug_assert!(value.is_none_or(|step| step > 0.0));
3161 if self.get(app).step_width == value {
3162 return;
3163 }
3164 self.get_mut(app).step_width = value;
3165 self.mark_needs_layout(app);
3166 }
3167
3168 pub fn step_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
3170 self.get(app).step_height
3171 }
3172
3173 pub fn set_step_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
3175 debug_assert!(value.is_none_or(|step| step > 0.0));
3176 if self.get(app).step_height == value {
3177 return;
3178 }
3179 self.get_mut(app).step_height = value;
3180 self.mark_needs_layout(app);
3181 }
3182
3183 fn child_constraints(
3184 self: RenderHandle<Self>,
3185 app: &mut App,
3186 child: AnyRenderBox,
3187 constraints: BoxConstraints,
3188 ) -> BoxConstraints {
3189 let (step_width, step_height) = {
3190 let this = self.get(app);
3191 (this.step_width, this.step_height)
3192 };
3193 let width = if constraints.has_tight_width() {
3194 None
3195 } else {
3196 Some(apply_step(
3197 child.get_max_intrinsic_width(app, constraints.max_height),
3198 step_width,
3199 ))
3200 };
3201 let height = step_height.map(|_| {
3202 apply_step(
3203 child.get_max_intrinsic_height(app, constraints.max_width),
3204 step_height,
3205 )
3206 });
3207 constraints.tighten(width, height)
3208 }
3209
3210 fn compute_size(
3212 self: RenderHandle<Self>,
3213 app: &mut App,
3214 constraints: BoxConstraints,
3215 layout_child: ChildLayouter,
3216 ) -> Size {
3217 match self.child(app) {
3218 Some(child) => {
3219 let child_constraints = self.child_constraints(app, child, constraints);
3220 layout_child(app, child, child_constraints)
3221 }
3222 None => constraints.smallest(),
3223 }
3224 }
3225}
3226
3227impl RenderObjectWithChildMixin for RenderIntrinsicWidth {
3228 type ChildType = AnyRenderBox;
3229
3230 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3231 &self.get(app).child
3232 }
3233
3234 fn child_data_mut(
3235 self: RenderHandle<Self>,
3236 app: &mut App,
3237 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3238 &mut self.get_mut(app).child
3239 }
3240}
3241
3242impl RenderProxyBoxMixin for RenderIntrinsicWidth {}
3243
3244impl RenderObject for RenderIntrinsicWidth {
3245 crate::render_object_accessors!();
3246
3247 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3248 let constraints = self.constraints(app);
3249 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
3250 self.set_size(app, size);
3251 }
3252
3253 fn paint(
3254 self: RenderHandle<Self>,
3255 app: &mut App,
3256 context: &mut PaintingContext,
3257 offset: Offset,
3258 ) {
3259 RenderProxyBoxMixin::paint(self, app, context, offset);
3260 }
3261
3262 fn visit_children(
3263 self: RenderHandle<Self>,
3264 app: &App,
3265 visitor: &mut dyn FnMut(AnyRenderObject),
3266 ) {
3267 if let Some(child) = self.child(app) {
3268 visitor(child.as_object());
3269 }
3270 }
3271}
3272
3273impl RenderBox for RenderIntrinsicWidth {
3274 crate::render_box_accessors!();
3275
3276 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3277 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3278 }
3279
3280 fn apply_paint_transform(
3281 self: RenderHandle<Self>,
3282 app: &App,
3283 child: AnyRenderObject,
3284 transform: &mut Matrix4,
3285 ) {
3286 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3287 }
3288
3289 fn hit_test_children(
3290 self: RenderHandle<Self>,
3291 app: &mut App,
3292 result: &mut BoxHitTestResult<'_>,
3293 position: Offset,
3294 ) -> bool {
3295 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3296 }
3297
3298 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3299 self.as_box().get_max_intrinsic_width(app, height)
3300 }
3301
3302 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3303 let Some(child) = self.child(app) else {
3304 return 0.0;
3305 };
3306 let width = child.get_max_intrinsic_width(app, height);
3307 apply_step(width, self.get(app).step_width)
3308 }
3309
3310 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3311 let Some(child) = self.child(app) else {
3312 return 0.0;
3313 };
3314 let width = if width.is_finite() {
3315 width
3316 } else {
3317 self.as_box().get_max_intrinsic_width(app, f64::INFINITY)
3318 };
3319 debug_assert!(width.is_finite());
3320 let height = child.get_min_intrinsic_height(app, width);
3321 apply_step(height, self.get(app).step_height)
3322 }
3323
3324 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3325 let Some(child) = self.child(app) else {
3326 return 0.0;
3327 };
3328 let width = if width.is_finite() {
3329 width
3330 } else {
3331 self.as_box().get_max_intrinsic_width(app, f64::INFINITY)
3332 };
3333 debug_assert!(width.is_finite());
3334 let height = child.get_max_intrinsic_height(app, width);
3335 apply_step(height, self.get(app).step_height)
3336 }
3337
3338 fn compute_distance_to_actual_baseline(
3339 self: RenderHandle<Self>,
3340 app: &mut App,
3341 baseline: TextBaseline,
3342 ) -> Option<f64> {
3343 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3344 }
3345
3346 fn compute_dry_layout(
3347 self: RenderHandle<Self>,
3348 app: &mut App,
3349 constraints: BoxConstraints,
3350 ) -> Size {
3351 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
3352 }
3353
3354 fn compute_dry_baseline(
3355 self: RenderHandle<Self>,
3356 app: &mut App,
3357 constraints: BoxConstraints,
3358 baseline: TextBaseline,
3359 ) -> Option<f64> {
3360 let child = self.child(app)?;
3361 let child_constraints = self.child_constraints(app, child, constraints);
3362 child.get_dry_baseline(app, child_constraints, baseline)
3363 }
3364}
3365
3366pub struct RenderIntrinsicHeight {
3382 render_object: RenderObjectData,
3383 render_box: RenderBoxData,
3384 child: RenderObjectWithChildData<AnyRenderBox>,
3385}
3386
3387impl RenderIntrinsicHeight {
3388 pub fn new(app: &mut App, child: Option<AnyRenderBox>) -> RenderHandle<RenderIntrinsicHeight> {
3390 let this = RenderHandle::new_box(
3391 app,
3392 RenderIntrinsicHeight {
3393 render_object: RenderObjectData::new(),
3394 render_box: RenderBoxData::new(),
3395 child: RenderObjectWithChildData::new(),
3396 },
3397 );
3398 this.set_child(app, child);
3399 this
3400 }
3401
3402 fn child_constraints(
3403 self: RenderHandle<Self>,
3404 app: &mut App,
3405 child: AnyRenderBox,
3406 constraints: BoxConstraints,
3407 ) -> BoxConstraints {
3408 if constraints.has_tight_height() {
3409 return constraints;
3410 }
3411 let height = child.get_max_intrinsic_height(app, constraints.max_width);
3412 constraints.tighten(None, Some(height))
3413 }
3414
3415 fn compute_size(
3417 self: RenderHandle<Self>,
3418 app: &mut App,
3419 constraints: BoxConstraints,
3420 layout_child: ChildLayouter,
3421 ) -> Size {
3422 match self.child(app) {
3423 Some(child) => {
3424 let child_constraints = self.child_constraints(app, child, constraints);
3425 layout_child(app, child, child_constraints)
3426 }
3427 None => constraints.smallest(),
3428 }
3429 }
3430}
3431
3432impl RenderObjectWithChildMixin for RenderIntrinsicHeight {
3433 type ChildType = AnyRenderBox;
3434
3435 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3436 &self.get(app).child
3437 }
3438
3439 fn child_data_mut(
3440 self: RenderHandle<Self>,
3441 app: &mut App,
3442 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3443 &mut self.get_mut(app).child
3444 }
3445}
3446
3447impl RenderProxyBoxMixin for RenderIntrinsicHeight {}
3448
3449impl RenderObject for RenderIntrinsicHeight {
3450 crate::render_object_accessors!();
3451
3452 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3453 let constraints = self.constraints(app);
3454 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
3455 self.set_size(app, size);
3456 }
3457
3458 fn paint(
3459 self: RenderHandle<Self>,
3460 app: &mut App,
3461 context: &mut PaintingContext,
3462 offset: Offset,
3463 ) {
3464 RenderProxyBoxMixin::paint(self, app, context, offset);
3465 }
3466
3467 fn visit_children(
3468 self: RenderHandle<Self>,
3469 app: &App,
3470 visitor: &mut dyn FnMut(AnyRenderObject),
3471 ) {
3472 if let Some(child) = self.child(app) {
3473 visitor(child.as_object());
3474 }
3475 }
3476}
3477
3478impl RenderBox for RenderIntrinsicHeight {
3479 crate::render_box_accessors!();
3480
3481 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3482 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3483 }
3484
3485 fn apply_paint_transform(
3486 self: RenderHandle<Self>,
3487 app: &App,
3488 child: AnyRenderObject,
3489 transform: &mut Matrix4,
3490 ) {
3491 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3492 }
3493
3494 fn hit_test_children(
3495 self: RenderHandle<Self>,
3496 app: &mut App,
3497 result: &mut BoxHitTestResult<'_>,
3498 position: Offset,
3499 ) -> bool {
3500 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3501 }
3502
3503 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3504 let Some(child) = self.child(app) else {
3505 return 0.0;
3506 };
3507 let height = if height.is_finite() {
3508 height
3509 } else {
3510 child.get_max_intrinsic_height(app, f64::INFINITY)
3511 };
3512 debug_assert!(height.is_finite());
3513 child.get_min_intrinsic_width(app, height)
3514 }
3515
3516 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3517 let Some(child) = self.child(app) else {
3518 return 0.0;
3519 };
3520 let height = if height.is_finite() {
3521 height
3522 } else {
3523 child.get_max_intrinsic_height(app, f64::INFINITY)
3524 };
3525 debug_assert!(height.is_finite());
3526 child.get_max_intrinsic_width(app, height)
3527 }
3528
3529 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3530 self.as_box().get_max_intrinsic_height(app, width)
3531 }
3532
3533 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3534 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
3535 }
3536
3537 fn compute_distance_to_actual_baseline(
3538 self: RenderHandle<Self>,
3539 app: &mut App,
3540 baseline: TextBaseline,
3541 ) -> Option<f64> {
3542 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3543 }
3544
3545 fn compute_dry_layout(
3546 self: RenderHandle<Self>,
3547 app: &mut App,
3548 constraints: BoxConstraints,
3549 ) -> Size {
3550 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
3551 }
3552
3553 fn compute_dry_baseline(
3554 self: RenderHandle<Self>,
3555 app: &mut App,
3556 constraints: BoxConstraints,
3557 baseline: TextBaseline,
3558 ) -> Option<f64> {
3559 let child = self.child(app)?;
3560 let child_constraints = self.child_constraints(app, child, constraints);
3561 child.get_dry_baseline(app, child_constraints, baseline)
3562 }
3563}
3564
3565pub trait CustomClipper<T>: 'static {
3579 fn reclip(&self) -> Option<&Rc<dyn Listenable>> {
3585 None
3586 }
3587
3588 fn get_clip(&self, size: Size) -> T;
3591
3592 fn should_reclip(&self, old_clipper: &dyn CustomClipper<T>) -> bool;
3610
3611 fn as_any(&self) -> &dyn Any;
3613}
3614
3615impl<T: 'static> Listenable for dyn CustomClipper<T> {
3616 fn add_listener(&self, app: &mut App, listener: Listener) {
3620 if let Some(reclip) = self.reclip() {
3621 reclip.add_listener(app, listener);
3622 }
3623 }
3624
3625 fn remove_listener(&self, app: &mut App, listener: &Listener) {
3628 if let Some(reclip) = self.reclip() {
3629 reclip.remove_listener(app, listener);
3630 }
3631 }
3632}
3633
3634pub struct RenderCustomClipData<T> {
3636 clipper: Option<Rc<dyn CustomClipper<T>>>,
3637 clip: Option<T>,
3638 clip_behavior: Clip,
3639}
3640
3641impl<T> RenderCustomClipData<T> {
3642 pub fn new(
3644 clipper: Option<Rc<dyn CustomClipper<T>>>,
3645 clip_behavior: Clip,
3646 ) -> RenderCustomClipData<T> {
3647 RenderCustomClipData {
3648 clipper,
3649 clip: None,
3650 clip_behavior,
3651 }
3652 }
3653}
3654
3655pub struct ShapeBorderClipper {
3657 pub shape: Box<dyn ShapeBorder>,
3659 pub text_direction: Option<TextDirection>,
3664}
3665
3666impl ShapeBorderClipper {
3667 pub fn new(shape: Box<dyn ShapeBorder>, text_direction: Option<TextDirection>) -> Self {
3674 ShapeBorderClipper {
3675 shape,
3676 text_direction,
3677 }
3678 }
3679}
3680
3681impl CustomClipper<Arc<Path>> for ShapeBorderClipper {
3682 fn get_clip(&self, size: Size) -> Arc<Path> {
3683 self.shape
3684 .get_outer_path(Offset::ZERO & size, self.text_direction)
3685 }
3686
3687 fn should_reclip(&self, old_clipper: &dyn CustomClipper<Arc<Path>>) -> bool {
3688 let Some(old_clipper) = old_clipper.as_any().downcast_ref::<ShapeBorderClipper>() else {
3689 return true;
3690 };
3691 !old_clipper.shape.eq_shape(&*self.shape)
3692 || old_clipper.text_direction != self.text_direction
3693 }
3694
3695 fn as_any(&self) -> &dyn Any {
3696 self
3697 }
3698}
3699
3700pub trait RenderCustomClip<T: Clone + 'static>: RenderProxyBoxMixin {
3706 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<T>;
3708
3709 fn custom_clip_data_mut(
3711 self: RenderHandle<Self>,
3712 app: &mut App,
3713 ) -> &mut RenderCustomClipData<T>;
3714
3715 fn default_clip(self: RenderHandle<Self>, app: &App) -> T;
3717
3718 fn clipper(self: RenderHandle<Self>, app: &App) -> Option<Rc<dyn CustomClipper<T>>> {
3720 self.custom_clip_data(app).clipper.clone()
3721 }
3722
3723 fn set_clipper(
3725 self: RenderHandle<Self>,
3726 app: &mut App,
3727 new_clipper: Option<Rc<dyn CustomClipper<T>>>,
3728 ) {
3729 let old_clipper = self.clipper(app);
3730 if same_instance(old_clipper.as_ref(), new_clipper.as_ref()) {
3731 return;
3732 }
3733 self.custom_clip_data_mut(app).clipper = new_clipper.clone();
3734 debug_assert!(new_clipper.is_some() || old_clipper.is_some());
3735 let reclip = match (&new_clipper, &old_clipper) {
3736 (Some(new_clipper), Some(old_clipper)) => {
3737 new_clipper.as_any().type_id() != old_clipper.as_any().type_id()
3738 || new_clipper.should_reclip(&**old_clipper)
3739 }
3740 _ => true,
3741 };
3742 if reclip {
3743 self.mark_needs_clip(app);
3744 }
3745 if self.attached(app) {
3746 if let Some(old_clipper) = &old_clipper {
3747 old_clipper.remove_listener(app, &self.clip_listener());
3748 }
3749 if let Some(new_clipper) = &new_clipper {
3750 new_clipper.add_listener(app, self.clip_listener());
3751 }
3752 }
3753 }
3754
3755 fn did_attach(self: RenderHandle<Self>, app: &mut App) {
3757 if let Some(clipper) = self.clipper(app) {
3758 clipper.add_listener(app, self.clip_listener());
3759 }
3760 }
3761
3762 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
3764 if let Some(clipper) = self.clipper(app) {
3765 clipper.remove_listener(app, &self.clip_listener());
3766 }
3767 }
3768
3769 fn mark_needs_clip(self: RenderHandle<Self>, app: &mut App) {
3771 self.custom_clip_data_mut(app).clip = None;
3772 self.mark_needs_paint(app);
3773 }
3774
3775 fn clip_listener(self: RenderHandle<Self>) -> Listener {
3777 Listener::handle_method(self.handle(), mark_needs_clip::<Self, T>)
3778 }
3779
3780 fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
3782 self.custom_clip_data(app).clip_behavior
3783 }
3784
3785 fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
3787 if value != self.clip_behavior(app) {
3788 self.custom_clip_data_mut(app).clip_behavior = value;
3789 self.mark_needs_paint(app);
3790 }
3791 }
3792
3793 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3795 let old_size = self.has_size(app).then(|| self.size(app));
3796 RenderProxyBoxMixin::perform_layout(self, app);
3797 if old_size != Some(self.size(app)) {
3798 self.custom_clip_data_mut(app).clip = None;
3799 }
3800 }
3801
3802 fn update_clip(self: RenderHandle<Self>, app: &mut App) {
3804 if self.custom_clip_data(app).clip.is_some() {
3805 return;
3806 }
3807 let clip = match self.clipper(app) {
3808 Some(clipper) => clipper.get_clip(self.size(app)),
3809 None => self.default_clip(app),
3810 };
3811 self.custom_clip_data_mut(app).clip = Some(clip);
3812 }
3813
3814 fn clip(self: RenderHandle<Self>, app: &App) -> T {
3816 self.custom_clip_data(app)
3817 .clip
3818 .clone()
3819 .expect("update_clip computes the clip")
3820 }
3821}
3822
3823fn mark_needs_clip<C: RenderCustomClip<T>, T: Clone + 'static>(this: Handle<C>, app: &mut App) {
3824 RenderCustomClip::mark_needs_clip(RenderHandle::from_handle(this), app);
3825}
3826
3827pub struct RenderClipRect {
3833 render_object: RenderObjectData,
3834 render_box: RenderBoxData,
3835 child: RenderObjectWithChildData<AnyRenderBox>,
3836 custom_clip: RenderCustomClipData<Rect>,
3837}
3838
3839impl RenderClipRect {
3840 pub fn new(
3847 app: &mut App,
3848 clipper: Option<Rc<dyn CustomClipper<Rect>>>,
3849 clip_behavior: Clip,
3850 child: Option<AnyRenderBox>,
3851 ) -> RenderHandle<RenderClipRect> {
3852 let this = RenderHandle::new_box(
3853 app,
3854 RenderClipRect {
3855 render_object: RenderObjectData::new(),
3856 render_box: RenderBoxData::new(),
3857 child: RenderObjectWithChildData::new(),
3858 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
3859 },
3860 );
3861 this.set_child(app, child);
3862 this
3863 }
3864}
3865
3866impl RenderObjectWithChildMixin for RenderClipRect {
3867 type ChildType = AnyRenderBox;
3868
3869 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3870 &self.get(app).child
3871 }
3872
3873 fn child_data_mut(
3874 self: RenderHandle<Self>,
3875 app: &mut App,
3876 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3877 &mut self.get_mut(app).child
3878 }
3879}
3880
3881impl RenderProxyBoxMixin for RenderClipRect {}
3882
3883impl RenderCustomClip<Rect> for RenderClipRect {
3884 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Rect> {
3885 &self.get(app).custom_clip
3886 }
3887
3888 fn custom_clip_data_mut(
3889 self: RenderHandle<Self>,
3890 app: &mut App,
3891 ) -> &mut RenderCustomClipData<Rect> {
3892 &mut self.get_mut(app).custom_clip
3893 }
3894
3895 fn default_clip(self: RenderHandle<Self>, app: &App) -> Rect {
3896 Offset::ZERO & self.size(app)
3897 }
3898}
3899
3900impl RenderObject for RenderClipRect {
3901 crate::render_object_accessors!();
3902
3903 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
3904 if let Some(child) = self.child(app) {
3905 child.as_object().attach(app, owner);
3906 }
3907 RenderCustomClip::did_attach(self, app);
3908 }
3909
3910 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
3911 RenderCustomClip::did_detach(self, app);
3912 if let Some(child) = self.child(app) {
3913 child.as_object().detach(app);
3914 }
3915 }
3916
3917 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3918 RenderCustomClip::perform_layout(self, app);
3919 }
3920
3921 fn paint(
3922 self: RenderHandle<Self>,
3923 app: &mut App,
3924 context: &mut PaintingContext,
3925 offset: Offset,
3926 ) {
3927 if let Some(child) = self.child(app) {
3928 let clip_behavior = self.clip_behavior(app);
3929 if clip_behavior != Clip::None {
3930 self.update_clip(app);
3931 let clip = self.clip(app);
3932 let old = self.as_object().layer_as::<ClipRectLayer>(app);
3933 let layer = context.push_clip_rect(
3934 app,
3935 self.as_object().needs_compositing(app),
3936 offset,
3937 clip,
3938 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
3939 clip_behavior,
3940 old,
3941 );
3942 self.as_object()
3943 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
3944 } else {
3945 context.paint_child(app, child.as_object(), offset);
3946 self.as_object().set_layer(app, None);
3947 }
3948 } else {
3949 self.as_object().set_layer(app, None);
3950 }
3951 }
3952
3953 fn visit_children(
3954 self: RenderHandle<Self>,
3955 app: &App,
3956 visitor: &mut dyn FnMut(AnyRenderObject),
3957 ) {
3958 if let Some(child) = self.child(app) {
3959 visitor(child.as_object());
3960 }
3961 }
3962}
3963
3964impl RenderBox for RenderClipRect {
3965 crate::render_box_accessors!();
3966
3967 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3968 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3969 }
3970
3971 fn apply_paint_transform(
3972 self: RenderHandle<Self>,
3973 app: &App,
3974 child: AnyRenderObject,
3975 transform: &mut Matrix4,
3976 ) {
3977 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3978 }
3979
3980 fn hit_test(
3981 self: RenderHandle<Self>,
3982 app: &mut App,
3983 result: &mut BoxHitTestResult<'_>,
3984 position: Offset,
3985 ) -> bool {
3986 if self.clipper(app).is_some() {
3987 self.update_clip(app);
3988 if !self.clip(app).contains(position) {
3989 return false;
3990 }
3991 }
3992 RenderBoxBase::hit_test(self, app, result, position)
3993 }
3994
3995 fn hit_test_children(
3996 self: RenderHandle<Self>,
3997 app: &mut App,
3998 result: &mut BoxHitTestResult<'_>,
3999 position: Offset,
4000 ) -> bool {
4001 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4002 }
4003
4004 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4005 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4006 }
4007
4008 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4009 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4010 }
4011
4012 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4013 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4014 }
4015
4016 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4017 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4018 }
4019
4020 fn compute_distance_to_actual_baseline(
4021 self: RenderHandle<Self>,
4022 app: &mut App,
4023 baseline: TextBaseline,
4024 ) -> Option<f64> {
4025 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4026 }
4027
4028 fn compute_dry_baseline(
4029 self: RenderHandle<Self>,
4030 app: &mut App,
4031 constraints: BoxConstraints,
4032 baseline: TextBaseline,
4033 ) -> Option<f64> {
4034 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4035 }
4036
4037 fn compute_dry_layout(
4038 self: RenderHandle<Self>,
4039 app: &mut App,
4040 constraints: BoxConstraints,
4041 ) -> Size {
4042 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4043 }
4044}
4045
4046pub struct RenderClipRRect {
4052 render_object: RenderObjectData,
4053 render_box: RenderBoxData,
4054 child: RenderObjectWithChildData<AnyRenderBox>,
4055 custom_clip: RenderCustomClipData<RRect>,
4056 border_radius: BorderRadiusGeometry,
4057 text_direction: Option<TextDirection>,
4058}
4059
4060impl RenderClipRRect {
4061 pub fn new(
4070 app: &mut App,
4071 border_radius: BorderRadiusGeometry,
4072 clipper: Option<Rc<dyn CustomClipper<RRect>>>,
4073 clip_behavior: Clip,
4074 text_direction: Option<TextDirection>,
4075 child: Option<AnyRenderBox>,
4076 ) -> RenderHandle<RenderClipRRect> {
4077 let this = RenderHandle::new_box(
4078 app,
4079 RenderClipRRect {
4080 render_object: RenderObjectData::new(),
4081 render_box: RenderBoxData::new(),
4082 child: RenderObjectWithChildData::new(),
4083 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4084 border_radius,
4085 text_direction,
4086 },
4087 );
4088 this.set_child(app, child);
4089 this
4090 }
4091
4092 pub fn border_radius(self: RenderHandle<Self>, app: &App) -> BorderRadiusGeometry {
4099 self.get(app).border_radius
4100 }
4101
4102 pub fn set_border_radius(self: RenderHandle<Self>, app: &mut App, value: BorderRadiusGeometry) {
4104 if self.get(app).border_radius == value {
4105 return;
4106 }
4107 self.get_mut(app).border_radius = value;
4108 self.mark_needs_clip(app);
4109 }
4110
4111 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
4113 self.get(app).text_direction
4114 }
4115
4116 pub fn set_text_direction(
4118 self: RenderHandle<Self>,
4119 app: &mut App,
4120 value: Option<TextDirection>,
4121 ) {
4122 if self.get(app).text_direction == value {
4123 return;
4124 }
4125 self.get_mut(app).text_direction = value;
4126 self.mark_needs_clip(app);
4127 }
4128}
4129
4130impl RenderObjectWithChildMixin for RenderClipRRect {
4131 type ChildType = AnyRenderBox;
4132
4133 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4134 &self.get(app).child
4135 }
4136
4137 fn child_data_mut(
4138 self: RenderHandle<Self>,
4139 app: &mut App,
4140 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4141 &mut self.get_mut(app).child
4142 }
4143}
4144
4145impl RenderProxyBoxMixin for RenderClipRRect {}
4146
4147impl RenderCustomClip<RRect> for RenderClipRRect {
4148 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<RRect> {
4149 &self.get(app).custom_clip
4150 }
4151
4152 fn custom_clip_data_mut(
4153 self: RenderHandle<Self>,
4154 app: &mut App,
4155 ) -> &mut RenderCustomClipData<RRect> {
4156 &mut self.get_mut(app).custom_clip
4157 }
4158
4159 fn default_clip(self: RenderHandle<Self>, app: &App) -> RRect {
4160 let this = self.get(app);
4161 this.border_radius
4162 .resolve(this.text_direction)
4163 .to_rrect(Offset::ZERO & self.size(app))
4164 }
4165}
4166
4167impl RenderObject for RenderClipRRect {
4168 crate::render_object_accessors!();
4169
4170 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4171 if let Some(child) = self.child(app) {
4172 child.as_object().attach(app, owner);
4173 }
4174 RenderCustomClip::did_attach(self, app);
4175 }
4176
4177 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4178 RenderCustomClip::did_detach(self, app);
4179 if let Some(child) = self.child(app) {
4180 child.as_object().detach(app);
4181 }
4182 }
4183
4184 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4185 RenderCustomClip::perform_layout(self, app);
4186 }
4187
4188 fn paint(
4189 self: RenderHandle<Self>,
4190 app: &mut App,
4191 context: &mut PaintingContext,
4192 offset: Offset,
4193 ) {
4194 if let Some(child) = self.child(app) {
4195 let clip_behavior = self.clip_behavior(app);
4196 if clip_behavior != Clip::None {
4197 self.update_clip(app);
4198 let clip = self.clip(app);
4199 let old = self.as_object().layer_as::<ClipRRectLayer>(app);
4200 let layer = context.push_clip_rrect(
4201 app,
4202 self.as_object().needs_compositing(app),
4203 offset,
4204 clip.outer_rect(),
4205 clip,
4206 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4207 clip_behavior,
4208 old,
4209 );
4210 self.as_object()
4211 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4212 } else {
4213 context.paint_child(app, child.as_object(), offset);
4214 self.as_object().set_layer(app, None);
4215 }
4216 } else {
4217 self.as_object().set_layer(app, None);
4218 }
4219 }
4220
4221 fn visit_children(
4222 self: RenderHandle<Self>,
4223 app: &App,
4224 visitor: &mut dyn FnMut(AnyRenderObject),
4225 ) {
4226 if let Some(child) = self.child(app) {
4227 visitor(child.as_object());
4228 }
4229 }
4230}
4231
4232impl RenderBox for RenderClipRRect {
4233 crate::render_box_accessors!();
4234
4235 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4236 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4237 }
4238
4239 fn apply_paint_transform(
4240 self: RenderHandle<Self>,
4241 app: &App,
4242 child: AnyRenderObject,
4243 transform: &mut Matrix4,
4244 ) {
4245 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4246 }
4247
4248 fn hit_test(
4249 self: RenderHandle<Self>,
4250 app: &mut App,
4251 result: &mut BoxHitTestResult<'_>,
4252 position: Offset,
4253 ) -> bool {
4254 if self.clipper(app).is_some() {
4255 self.update_clip(app);
4256 if !self.clip(app).contains(position) {
4257 return false;
4258 }
4259 }
4260 RenderBoxBase::hit_test(self, app, result, position)
4261 }
4262
4263 fn hit_test_children(
4264 self: RenderHandle<Self>,
4265 app: &mut App,
4266 result: &mut BoxHitTestResult<'_>,
4267 position: Offset,
4268 ) -> bool {
4269 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4270 }
4271
4272 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4273 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4274 }
4275
4276 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4277 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4278 }
4279
4280 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4281 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4282 }
4283
4284 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4285 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4286 }
4287
4288 fn compute_distance_to_actual_baseline(
4289 self: RenderHandle<Self>,
4290 app: &mut App,
4291 baseline: TextBaseline,
4292 ) -> Option<f64> {
4293 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4294 }
4295
4296 fn compute_dry_baseline(
4297 self: RenderHandle<Self>,
4298 app: &mut App,
4299 constraints: BoxConstraints,
4300 baseline: TextBaseline,
4301 ) -> Option<f64> {
4302 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4303 }
4304
4305 fn compute_dry_layout(
4306 self: RenderHandle<Self>,
4307 app: &mut App,
4308 constraints: BoxConstraints,
4309 ) -> Size {
4310 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4311 }
4312}
4313
4314pub struct RenderClipOval {
4319 render_object: RenderObjectData,
4320 render_box: RenderBoxData,
4321 child: RenderObjectWithChildData<AnyRenderBox>,
4322 custom_clip: RenderCustomClipData<Rect>,
4323 cached_rect: Option<Rect>,
4324 cached_path: Option<Arc<Path>>,
4325}
4326
4327impl RenderClipOval {
4328 pub fn new(
4335 app: &mut App,
4336 clipper: Option<Rc<dyn CustomClipper<Rect>>>,
4337 clip_behavior: Clip,
4338 child: Option<AnyRenderBox>,
4339 ) -> RenderHandle<RenderClipOval> {
4340 let this = RenderHandle::new_box(
4341 app,
4342 RenderClipOval {
4343 render_object: RenderObjectData::new(),
4344 render_box: RenderBoxData::new(),
4345 child: RenderObjectWithChildData::new(),
4346 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4347 cached_rect: None,
4348 cached_path: None,
4349 },
4350 );
4351 this.set_child(app, child);
4352 this
4353 }
4354
4355 fn get_clip_path(self: RenderHandle<Self>, app: &mut App, rect: Rect) -> Arc<Path> {
4356 if self.get(app).cached_rect != Some(rect) {
4357 let radius = [(rect.width() / 2.0) as f32, (rect.height() / 2.0) as f32];
4358 let mut path = PathBuilder::new();
4359 path.rrect_radii_elliptical(rect, [radius; 4]);
4360 let this = self.get_mut(app);
4361 this.cached_rect = Some(rect);
4362 this.cached_path = Some(path.build());
4363 }
4364 self.get(app).cached_path.clone().expect("cached above")
4365 }
4366}
4367
4368impl RenderObjectWithChildMixin for RenderClipOval {
4369 type ChildType = AnyRenderBox;
4370
4371 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4372 &self.get(app).child
4373 }
4374
4375 fn child_data_mut(
4376 self: RenderHandle<Self>,
4377 app: &mut App,
4378 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4379 &mut self.get_mut(app).child
4380 }
4381}
4382
4383impl RenderProxyBoxMixin for RenderClipOval {}
4384
4385impl RenderCustomClip<Rect> for RenderClipOval {
4386 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Rect> {
4387 &self.get(app).custom_clip
4388 }
4389
4390 fn custom_clip_data_mut(
4391 self: RenderHandle<Self>,
4392 app: &mut App,
4393 ) -> &mut RenderCustomClipData<Rect> {
4394 &mut self.get_mut(app).custom_clip
4395 }
4396
4397 fn default_clip(self: RenderHandle<Self>, app: &App) -> Rect {
4398 Offset::ZERO & self.size(app)
4399 }
4400}
4401
4402impl RenderObject for RenderClipOval {
4403 crate::render_object_accessors!();
4404
4405 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4406 if let Some(child) = self.child(app) {
4407 child.as_object().attach(app, owner);
4408 }
4409 RenderCustomClip::did_attach(self, app);
4410 }
4411
4412 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4413 RenderCustomClip::did_detach(self, app);
4414 if let Some(child) = self.child(app) {
4415 child.as_object().detach(app);
4416 }
4417 }
4418
4419 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4420 RenderCustomClip::perform_layout(self, app);
4421 }
4422
4423 fn paint(
4424 self: RenderHandle<Self>,
4425 app: &mut App,
4426 context: &mut PaintingContext,
4427 offset: Offset,
4428 ) {
4429 if let Some(child) = self.child(app) {
4430 let clip_behavior = self.clip_behavior(app);
4431 if clip_behavior != Clip::None {
4432 self.update_clip(app);
4433 let clip = self.clip(app);
4434 let clip_path = self.get_clip_path(app, clip);
4435 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4436 let layer = context.push_clip_path(
4437 app,
4438 self.as_object().needs_compositing(app),
4439 offset,
4440 clip,
4441 clip_path,
4442 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4443 clip_behavior,
4444 old,
4445 );
4446 self.as_object()
4447 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4448 } else {
4449 context.paint_child(app, child.as_object(), offset);
4450 self.as_object().set_layer(app, None);
4451 }
4452 } else {
4453 self.as_object().set_layer(app, None);
4454 }
4455 }
4456
4457 fn visit_children(
4458 self: RenderHandle<Self>,
4459 app: &App,
4460 visitor: &mut dyn FnMut(AnyRenderObject),
4461 ) {
4462 if let Some(child) = self.child(app) {
4463 visitor(child.as_object());
4464 }
4465 }
4466}
4467
4468impl RenderBox for RenderClipOval {
4469 crate::render_box_accessors!();
4470
4471 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4472 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4473 }
4474
4475 fn apply_paint_transform(
4476 self: RenderHandle<Self>,
4477 app: &App,
4478 child: AnyRenderObject,
4479 transform: &mut Matrix4,
4480 ) {
4481 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4482 }
4483
4484 fn hit_test(
4485 self: RenderHandle<Self>,
4486 app: &mut App,
4487 result: &mut BoxHitTestResult<'_>,
4488 position: Offset,
4489 ) -> bool {
4490 self.update_clip(app);
4491 let clip = self.clip(app);
4492 let center = clip.center();
4493 let offset = Offset::new(
4495 (position.dx() - center.dx()) / clip.width(),
4496 (position.dy() - center.dy()) / clip.height(),
4497 );
4498 if offset.distance_squared() > 0.25 {
4500 return false;
4502 }
4503 RenderBoxBase::hit_test(self, app, result, position)
4504 }
4505
4506 fn hit_test_children(
4507 self: RenderHandle<Self>,
4508 app: &mut App,
4509 result: &mut BoxHitTestResult<'_>,
4510 position: Offset,
4511 ) -> bool {
4512 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4513 }
4514
4515 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4516 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4517 }
4518
4519 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4520 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4521 }
4522
4523 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4524 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4525 }
4526
4527 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4528 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4529 }
4530
4531 fn compute_distance_to_actual_baseline(
4532 self: RenderHandle<Self>,
4533 app: &mut App,
4534 baseline: TextBaseline,
4535 ) -> Option<f64> {
4536 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4537 }
4538
4539 fn compute_dry_baseline(
4540 self: RenderHandle<Self>,
4541 app: &mut App,
4542 constraints: BoxConstraints,
4543 baseline: TextBaseline,
4544 ) -> Option<f64> {
4545 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4546 }
4547
4548 fn compute_dry_layout(
4549 self: RenderHandle<Self>,
4550 app: &mut App,
4551 constraints: BoxConstraints,
4552 ) -> Size {
4553 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4554 }
4555}
4556
4557pub struct RenderClipPath {
4569 render_object: RenderObjectData,
4570 render_box: RenderBoxData,
4571 child: RenderObjectWithChildData<AnyRenderBox>,
4572 custom_clip: RenderCustomClipData<Arc<Path>>,
4573}
4574
4575impl RenderClipPath {
4576 pub fn new(
4585 app: &mut App,
4586 clipper: Option<Rc<dyn CustomClipper<Arc<Path>>>>,
4587 clip_behavior: Clip,
4588 child: Option<AnyRenderBox>,
4589 ) -> RenderHandle<RenderClipPath> {
4590 let this = RenderHandle::new_box(
4591 app,
4592 RenderClipPath {
4593 render_object: RenderObjectData::new(),
4594 render_box: RenderBoxData::new(),
4595 child: RenderObjectWithChildData::new(),
4596 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4597 },
4598 );
4599 this.set_child(app, child);
4600 this
4601 }
4602}
4603
4604impl RenderObjectWithChildMixin for RenderClipPath {
4605 type ChildType = AnyRenderBox;
4606
4607 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4608 &self.get(app).child
4609 }
4610
4611 fn child_data_mut(
4612 self: RenderHandle<Self>,
4613 app: &mut App,
4614 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4615 &mut self.get_mut(app).child
4616 }
4617}
4618
4619impl RenderProxyBoxMixin for RenderClipPath {}
4620
4621impl RenderCustomClip<Arc<Path>> for RenderClipPath {
4622 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Arc<Path>> {
4623 &self.get(app).custom_clip
4624 }
4625
4626 fn custom_clip_data_mut(
4627 self: RenderHandle<Self>,
4628 app: &mut App,
4629 ) -> &mut RenderCustomClipData<Arc<Path>> {
4630 &mut self.get_mut(app).custom_clip
4631 }
4632
4633 fn default_clip(self: RenderHandle<Self>, app: &App) -> Arc<Path> {
4634 let mut path = PathBuilder::new();
4635 path.rect((Offset::ZERO & self.size(app)).into());
4636 path.build()
4637 }
4638}
4639
4640impl RenderObject for RenderClipPath {
4641 crate::render_object_accessors!();
4642
4643 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4644 if let Some(child) = self.child(app) {
4645 child.as_object().attach(app, owner);
4646 }
4647 RenderCustomClip::did_attach(self, app);
4648 }
4649
4650 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4651 RenderCustomClip::did_detach(self, app);
4652 if let Some(child) = self.child(app) {
4653 child.as_object().detach(app);
4654 }
4655 }
4656
4657 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4658 RenderCustomClip::perform_layout(self, app);
4659 }
4660
4661 fn paint(
4662 self: RenderHandle<Self>,
4663 app: &mut App,
4664 context: &mut PaintingContext,
4665 offset: Offset,
4666 ) {
4667 if let Some(child) = self.child(app) {
4668 let clip_behavior = self.clip_behavior(app);
4669 if clip_behavior != Clip::None {
4670 self.update_clip(app);
4671 let clip = self.clip(app);
4672 let bounds = Offset::ZERO & self.size(app);
4673 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4674 let layer = context.push_clip_path(
4675 app,
4676 self.as_object().needs_compositing(app),
4677 offset,
4678 bounds,
4679 clip,
4680 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4681 clip_behavior,
4682 old,
4683 );
4684 self.as_object()
4685 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4686 } else {
4687 context.paint_child(app, child.as_object(), offset);
4688 self.as_object().set_layer(app, None);
4689 }
4690 } else {
4691 self.as_object().set_layer(app, None);
4692 }
4693 }
4694
4695 fn visit_children(
4696 self: RenderHandle<Self>,
4697 app: &App,
4698 visitor: &mut dyn FnMut(AnyRenderObject),
4699 ) {
4700 if let Some(child) = self.child(app) {
4701 visitor(child.as_object());
4702 }
4703 }
4704}
4705
4706impl RenderBox for RenderClipPath {
4707 crate::render_box_accessors!();
4708
4709 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4710 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4711 }
4712
4713 fn apply_paint_transform(
4714 self: RenderHandle<Self>,
4715 app: &App,
4716 child: AnyRenderObject,
4717 transform: &mut Matrix4,
4718 ) {
4719 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4720 }
4721
4722 fn hit_test(
4723 self: RenderHandle<Self>,
4724 app: &mut App,
4725 result: &mut BoxHitTestResult<'_>,
4726 position: Offset,
4727 ) -> bool {
4728 if self.clipper(app).is_some() {
4729 self.update_clip(app);
4730 let point = Point::new(position.dx() as f32, position.dy() as f32);
4731 if !self.clip(app).contains(point, FillRule::NonZero) {
4732 return false;
4733 }
4734 }
4735 RenderBoxBase::hit_test(self, app, result, position)
4736 }
4737
4738 fn hit_test_children(
4739 self: RenderHandle<Self>,
4740 app: &mut App,
4741 result: &mut BoxHitTestResult<'_>,
4742 position: Offset,
4743 ) -> bool {
4744 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4745 }
4746
4747 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4748 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4749 }
4750
4751 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4752 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4753 }
4754
4755 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4756 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4757 }
4758
4759 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4760 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4761 }
4762
4763 fn compute_distance_to_actual_baseline(
4764 self: RenderHandle<Self>,
4765 app: &mut App,
4766 baseline: TextBaseline,
4767 ) -> Option<f64> {
4768 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4769 }
4770
4771 fn compute_dry_baseline(
4772 self: RenderHandle<Self>,
4773 app: &mut App,
4774 constraints: BoxConstraints,
4775 baseline: TextBaseline,
4776 ) -> Option<f64> {
4777 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4778 }
4779
4780 fn compute_dry_layout(
4781 self: RenderHandle<Self>,
4782 app: &mut App,
4783 constraints: BoxConstraints,
4784 ) -> Size {
4785 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4786 }
4787}
4788
4789pub struct RenderClipRSuperellipse {
4795 render_object: RenderObjectData,
4796 render_box: RenderBoxData,
4797 child: RenderObjectWithChildData<AnyRenderBox>,
4798 custom_clip: RenderCustomClipData<RSuperellipse>,
4799 border_radius: BorderRadiusGeometry,
4800 text_direction: Option<TextDirection>,
4801}
4802
4803impl RenderClipRSuperellipse {
4804 pub fn new(
4813 app: &mut App,
4814 border_radius: BorderRadiusGeometry,
4815 clipper: Option<Rc<dyn CustomClipper<RSuperellipse>>>,
4816 clip_behavior: Clip,
4817 text_direction: Option<TextDirection>,
4818 child: Option<AnyRenderBox>,
4819 ) -> RenderHandle<RenderClipRSuperellipse> {
4820 let this = RenderHandle::new_box(
4821 app,
4822 RenderClipRSuperellipse {
4823 render_object: RenderObjectData::new(),
4824 render_box: RenderBoxData::new(),
4825 child: RenderObjectWithChildData::new(),
4826 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4827 border_radius,
4828 text_direction,
4829 },
4830 );
4831 this.set_child(app, child);
4832 this
4833 }
4834
4835 pub fn border_radius(self: RenderHandle<Self>, app: &App) -> BorderRadiusGeometry {
4842 self.get(app).border_radius
4843 }
4844
4845 pub fn set_border_radius(self: RenderHandle<Self>, app: &mut App, value: BorderRadiusGeometry) {
4847 if self.get(app).border_radius == value {
4848 return;
4849 }
4850 self.get_mut(app).border_radius = value;
4851 self.mark_needs_clip(app);
4852 }
4853
4854 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
4856 self.get(app).text_direction
4857 }
4858
4859 pub fn set_text_direction(
4861 self: RenderHandle<Self>,
4862 app: &mut App,
4863 value: Option<TextDirection>,
4864 ) {
4865 if self.get(app).text_direction == value {
4866 return;
4867 }
4868 self.get_mut(app).text_direction = value;
4869 self.mark_needs_clip(app);
4870 }
4871}
4872
4873impl RenderObjectWithChildMixin for RenderClipRSuperellipse {
4874 type ChildType = AnyRenderBox;
4875
4876 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4877 &self.get(app).child
4878 }
4879
4880 fn child_data_mut(
4881 self: RenderHandle<Self>,
4882 app: &mut App,
4883 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4884 &mut self.get_mut(app).child
4885 }
4886}
4887
4888impl RenderProxyBoxMixin for RenderClipRSuperellipse {}
4889
4890impl RenderCustomClip<RSuperellipse> for RenderClipRSuperellipse {
4891 fn custom_clip_data(
4892 self: RenderHandle<Self>,
4893 app: &App,
4894 ) -> &RenderCustomClipData<RSuperellipse> {
4895 &self.get(app).custom_clip
4896 }
4897
4898 fn custom_clip_data_mut(
4899 self: RenderHandle<Self>,
4900 app: &mut App,
4901 ) -> &mut RenderCustomClipData<RSuperellipse> {
4902 &mut self.get_mut(app).custom_clip
4903 }
4904
4905 fn default_clip(self: RenderHandle<Self>, app: &App) -> RSuperellipse {
4906 let this = self.get(app);
4907 this.border_radius
4908 .resolve(this.text_direction)
4909 .to_r_superellipse(Offset::ZERO & self.size(app))
4910 }
4911}
4912
4913impl RenderObject for RenderClipRSuperellipse {
4914 crate::render_object_accessors!();
4915
4916 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4917 if let Some(child) = self.child(app) {
4918 child.as_object().attach(app, owner);
4919 }
4920 RenderCustomClip::did_attach(self, app);
4921 }
4922
4923 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4924 RenderCustomClip::did_detach(self, app);
4925 if let Some(child) = self.child(app) {
4926 child.as_object().detach(app);
4927 }
4928 }
4929
4930 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4931 RenderCustomClip::perform_layout(self, app);
4932 }
4933
4934 fn paint(
4935 self: RenderHandle<Self>,
4936 app: &mut App,
4937 context: &mut PaintingContext,
4938 offset: Offset,
4939 ) {
4940 if let Some(child) = self.child(app) {
4941 let clip_behavior = self.clip_behavior(app);
4942 if clip_behavior != Clip::None {
4943 self.update_clip(app);
4944 let clip = self.clip(app);
4945 let mut clip_path = PathBuilder::new();
4946 clip_path.rsuperellipse_radii(
4947 clip.outer_rect().into(),
4948 rsuperellipse_radii_elliptical(clip),
4949 );
4950 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4951 let layer = context.push_clip_path(
4952 app,
4953 self.as_object().needs_compositing(app),
4954 offset,
4955 clip.outer_rect(),
4956 clip_path.build(),
4957 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4958 clip_behavior,
4959 old,
4960 );
4961 self.as_object()
4962 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4963 } else {
4964 context.paint_child(app, child.as_object(), offset);
4965 self.as_object().set_layer(app, None);
4966 }
4967 } else {
4968 self.as_object().set_layer(app, None);
4969 }
4970 }
4971
4972 fn visit_children(
4973 self: RenderHandle<Self>,
4974 app: &App,
4975 visitor: &mut dyn FnMut(AnyRenderObject),
4976 ) {
4977 if let Some(child) = self.child(app) {
4978 visitor(child.as_object());
4979 }
4980 }
4981}
4982
4983impl RenderBox for RenderClipRSuperellipse {
4984 crate::render_box_accessors!();
4985
4986 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4987 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4988 }
4989
4990 fn apply_paint_transform(
4991 self: RenderHandle<Self>,
4992 app: &App,
4993 child: AnyRenderObject,
4994 transform: &mut Matrix4,
4995 ) {
4996 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4997 }
4998
4999 fn hit_test(
5000 self: RenderHandle<Self>,
5001 app: &mut App,
5002 result: &mut BoxHitTestResult<'_>,
5003 position: Offset,
5004 ) -> bool {
5005 if self.clipper(app).is_some() {
5006 self.update_clip(app);
5007 if !self.clip(app).outer_rect().contains(position) {
5008 return false;
5009 }
5010 }
5011 RenderBoxBase::hit_test(self, app, result, position)
5012 }
5013
5014 fn hit_test_children(
5015 self: RenderHandle<Self>,
5016 app: &mut App,
5017 result: &mut BoxHitTestResult<'_>,
5018 position: Offset,
5019 ) -> bool {
5020 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5021 }
5022
5023 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5024 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5025 }
5026
5027 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5028 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5029 }
5030
5031 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5032 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5033 }
5034
5035 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5036 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5037 }
5038
5039 fn compute_distance_to_actual_baseline(
5040 self: RenderHandle<Self>,
5041 app: &mut App,
5042 baseline: TextBaseline,
5043 ) -> Option<f64> {
5044 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5045 }
5046
5047 fn compute_dry_baseline(
5048 self: RenderHandle<Self>,
5049 app: &mut App,
5050 constraints: BoxConstraints,
5051 baseline: TextBaseline,
5052 ) -> Option<f64> {
5053 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
5054 }
5055
5056 fn compute_dry_layout(
5057 self: RenderHandle<Self>,
5058 app: &mut App,
5059 constraints: BoxConstraints,
5060 ) -> Size {
5061 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
5062 }
5063}
5064
5065pub struct RenderTransform {
5067 render_object: RenderObjectData,
5068 render_box: RenderBoxData,
5069 child: RenderObjectWithChildData<AnyRenderBox>,
5070 origin: Option<Offset>,
5071 alignment: Option<AlignmentGeometry>,
5072 text_direction: Option<TextDirection>,
5073 transform_hit_tests: bool,
5074 transform: Matrix4,
5075}
5076
5077impl RenderTransform {
5078 pub fn new(
5080 app: &mut App,
5081 transform: Matrix4,
5082 origin: Option<Offset>,
5083 alignment: Option<AlignmentGeometry>,
5084 text_direction: Option<TextDirection>,
5085 transform_hit_tests: bool,
5086 child: Option<AnyRenderBox>,
5087 ) -> RenderHandle<RenderTransform> {
5088 let this = RenderHandle::new_box(
5089 app,
5090 RenderTransform {
5091 render_object: RenderObjectData::new(),
5092 render_box: RenderBoxData::new(),
5093 child: RenderObjectWithChildData::new(),
5094 origin,
5095 alignment,
5096 text_direction,
5097 transform_hit_tests,
5098 transform,
5099 },
5100 );
5101 this.set_child(app, child);
5102 this
5103 }
5104
5105 pub fn origin(self: RenderHandle<Self>, app: &App) -> Option<Offset> {
5111 self.get(app).origin
5112 }
5113
5114 pub fn set_origin(self: RenderHandle<Self>, app: &mut App, value: Option<Offset>) {
5116 if self.get(app).origin == value {
5117 return;
5118 }
5119 self.get_mut(app).origin = value;
5120 self.mark_needs_paint(app);
5121 }
5122
5123 pub fn alignment(self: RenderHandle<Self>, app: &App) -> Option<AlignmentGeometry> {
5137 self.get(app).alignment
5138 }
5139
5140 pub fn set_alignment(
5142 self: RenderHandle<Self>,
5143 app: &mut App,
5144 value: Option<AlignmentGeometry>,
5145 ) {
5146 if self.get(app).alignment == value {
5147 return;
5148 }
5149 self.get_mut(app).alignment = value;
5150 self.mark_needs_paint(app);
5151 }
5152
5153 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
5158 self.get(app).text_direction
5159 }
5160
5161 pub fn set_text_direction(
5163 self: RenderHandle<Self>,
5164 app: &mut App,
5165 value: Option<TextDirection>,
5166 ) {
5167 if self.get(app).text_direction == value {
5168 return;
5169 }
5170 self.get_mut(app).text_direction = value;
5171 self.mark_needs_paint(app);
5172 }
5173
5174 pub fn transform_hit_tests(self: RenderHandle<Self>, app: &App) -> bool {
5182 self.get(app).transform_hit_tests
5183 }
5184
5185 pub fn set_transform_hit_tests(self: RenderHandle<Self>, app: &mut App, value: bool) {
5187 self.get_mut(app).transform_hit_tests = value;
5188 }
5189
5190 pub fn set_transform(self: RenderHandle<Self>, app: &mut App, value: Matrix4) {
5196 if self.get(app).transform == value {
5197 return;
5198 }
5199 self.get_mut(app).transform = value;
5200 self.mark_needs_paint(app);
5201 }
5202
5203 pub fn set_identity(self: RenderHandle<Self>, app: &mut App) {
5205 self.get_mut(app).transform = Matrix4::IDENTITY;
5206 self.mark_needs_paint(app);
5207 }
5208
5209 pub fn rotate_x(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5211 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5212 #[rustfmt::skip]
5213 let rotation = Matrix4::from_flutter_array(&[
5214 1.0, 0.0, 0.0, 0.0,
5215 0.0, cos, sin, 0.0,
5216 0.0, -sin, cos, 0.0,
5217 0.0, 0.0, 0.0, 1.0,
5218 ]);
5219 self.concat(app, &rotation);
5220 }
5221
5222 pub fn rotate_y(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5224 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5225 #[rustfmt::skip]
5226 let rotation = Matrix4::from_flutter_array(&[
5227 cos, 0.0, -sin, 0.0,
5228 0.0, 1.0, 0.0, 0.0,
5229 sin, 0.0, cos, 0.0,
5230 0.0, 0.0, 0.0, 1.0,
5231 ]);
5232 self.concat(app, &rotation);
5233 }
5234
5235 pub fn rotate_z(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5237 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5238 #[rustfmt::skip]
5239 let rotation = Matrix4::from_flutter_array(&[
5240 cos, sin, 0.0, 0.0,
5241 -sin, cos, 0.0, 0.0,
5242 0.0, 0.0, 1.0, 0.0,
5243 0.0, 0.0, 0.0, 1.0,
5244 ]);
5245 self.concat(app, &rotation);
5246 }
5247
5248 pub fn translate(self: RenderHandle<Self>, app: &mut App, x: f64, y: f64, z: f64) {
5250 #[rustfmt::skip]
5251 let translation = Matrix4::from_flutter_array(&[
5252 1.0, 0.0, 0.0, 0.0,
5253 0.0, 1.0, 0.0, 0.0,
5254 0.0, 0.0, 1.0, 0.0,
5255 x as f32, y as f32, z as f32, 1.0,
5256 ]);
5257 self.concat(app, &translation);
5258 }
5259
5260 pub fn scale(self: RenderHandle<Self>, app: &mut App, x: f64, y: Option<f64>, z: Option<f64>) {
5262 let (y, z) = (y.unwrap_or(x) as f32, z.unwrap_or(x) as f32);
5263 #[rustfmt::skip]
5264 let scale = Matrix4::from_flutter_array(&[
5265 x as f32, 0.0, 0.0, 0.0,
5266 0.0, y, 0.0, 0.0,
5267 0.0, 0.0, z, 0.0,
5268 0.0, 0.0, 0.0, 1.0,
5269 ]);
5270 self.concat(app, &scale);
5271 }
5272
5273 fn concat(self: RenderHandle<Self>, app: &mut App, other: &Matrix4) {
5276 crate::object::multiply(&mut self.get_mut(app).transform, other);
5277 self.mark_needs_paint(app);
5278 }
5279
5280 fn effective_transform(self: RenderHandle<Self>, app: &App) -> Matrix4 {
5283 let this = self.get(app);
5284 let resolved_alignment = this
5285 .alignment
5286 .map(|alignment| alignment.resolve(this.text_direction));
5287 let origin = this.origin;
5288 if origin.is_none() && resolved_alignment.is_none() {
5289 return this.transform;
5290 }
5291 let mut result = Matrix4::IDENTITY;
5292 if let Some(origin) = origin {
5293 crate::object::translate(&mut result, origin.dx(), origin.dy());
5294 }
5295 let translation = resolved_alignment.map(|alignment| alignment.along_size(self.size(app)));
5296 if let Some(translation) = translation {
5297 crate::object::translate(&mut result, translation.dx(), translation.dy());
5298 }
5299 crate::object::multiply(&mut result, &self.get(app).transform);
5300 if let Some(translation) = translation {
5301 crate::object::translate(&mut result, -translation.dx(), -translation.dy());
5302 }
5303 if let Some(origin) = origin {
5304 crate::object::translate(&mut result, -origin.dx(), -origin.dy());
5305 }
5306 result
5307 }
5308}
5309
5310impl RenderObjectWithChildMixin for RenderTransform {
5311 type ChildType = AnyRenderBox;
5312
5313 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5314 &self.get(app).child
5315 }
5316
5317 fn child_data_mut(
5318 self: RenderHandle<Self>,
5319 app: &mut App,
5320 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5321 &mut self.get_mut(app).child
5322 }
5323}
5324
5325impl RenderProxyBoxMixin for RenderTransform {}
5326
5327impl RenderObject for RenderTransform {
5328 crate::render_object_accessors!();
5329
5330 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5331 RenderProxyBoxMixin::perform_layout(self, app);
5332 }
5333
5334 fn paint(
5335 self: RenderHandle<Self>,
5336 app: &mut App,
5337 context: &mut PaintingContext,
5338 offset: Offset,
5339 ) {
5340 if self.child(app).is_none() {
5341 return;
5342 }
5343 let transform = self.effective_transform(app);
5344 let Some(child_offset) = get_as_translation(transform) else {
5345 let determinant = transform.determinant();
5348 if determinant == 0.0 || !determinant.is_finite() {
5349 self.as_object().set_layer(app, None);
5350 return;
5351 }
5352 let old = self.as_object().layer_as::<TransformLayer>(app);
5353 let layer = context.push_transform(
5354 app,
5355 self.as_object().needs_compositing(app),
5356 offset,
5357 transform,
5358 |app, context, offset| {
5359 RenderProxyBoxMixin::paint(self, app, context, offset);
5360 },
5361 old,
5362 );
5363 self.as_object()
5364 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5365 return;
5366 };
5367 RenderProxyBoxMixin::paint(self, app, context, offset + child_offset);
5368 self.as_object().set_layer(app, None);
5369 }
5370
5371 fn visit_children(
5372 self: RenderHandle<Self>,
5373 app: &App,
5374 visitor: &mut dyn FnMut(AnyRenderObject),
5375 ) {
5376 if let Some(child) = self.child(app) {
5377 visitor(child.as_object());
5378 }
5379 }
5380}
5381
5382impl RenderBox for RenderTransform {
5383 crate::render_box_accessors!();
5384
5385 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
5386 RenderProxyBoxMixin::setup_parent_data(self, app, child);
5387 }
5388
5389 fn apply_paint_transform(
5390 self: RenderHandle<Self>,
5391 app: &App,
5392 _child: AnyRenderObject,
5393 transform: &mut Matrix4,
5394 ) {
5395 crate::object::multiply(transform, &self.effective_transform(app));
5396 }
5397
5398 fn hit_test(
5399 self: RenderHandle<Self>,
5400 app: &mut App,
5401 result: &mut BoxHitTestResult<'_>,
5402 position: Offset,
5403 ) -> bool {
5404 RenderBox::hit_test_children(self, app, result, position)
5409 }
5410
5411 fn hit_test_children(
5412 self: RenderHandle<Self>,
5413 app: &mut App,
5414 result: &mut BoxHitTestResult<'_>,
5415 position: Offset,
5416 ) -> bool {
5417 let transform = self
5418 .transform_hit_tests(app)
5419 .then(|| self.effective_transform(app));
5420 result.add_with_paint_transform(transform, position, |result, position| {
5421 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5422 })
5423 }
5424
5425 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5426 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5427 }
5428
5429 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5430 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5431 }
5432
5433 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5434 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5435 }
5436
5437 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5438 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5439 }
5440
5441 fn compute_distance_to_actual_baseline(
5442 self: RenderHandle<Self>,
5443 app: &mut App,
5444 baseline: TextBaseline,
5445 ) -> Option<f64> {
5446 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5447 }
5448
5449 fn compute_dry_baseline(
5450 self: RenderHandle<Self>,
5451 app: &mut App,
5452 constraints: BoxConstraints,
5453 baseline: TextBaseline,
5454 ) -> Option<f64> {
5455 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
5456 }
5457
5458 fn compute_dry_layout(
5459 self: RenderHandle<Self>,
5460 app: &mut App,
5461 constraints: BoxConstraints,
5462 ) -> Size {
5463 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
5464 }
5465}
5466
5467pub struct RenderFittedBox {
5469 render_object: RenderObjectData,
5470 render_box: RenderBoxData,
5471 child: RenderObjectWithChildData<AnyRenderBox>,
5472 fit: BoxFit,
5473 alignment: AlignmentGeometry,
5474 text_direction: Option<TextDirection>,
5475 resolved_alignment: Option<Alignment>,
5476 clip_behavior: Clip,
5477 has_visual_overflow: Option<bool>,
5478 transform: Option<Matrix4>,
5479}
5480
5481fn fit_affects_layout(fit: BoxFit) -> bool {
5483 match fit {
5484 BoxFit::ScaleDown => true,
5485 BoxFit::Contain
5486 | BoxFit::Cover
5487 | BoxFit::Fill
5488 | BoxFit::FitHeight
5489 | BoxFit::FitWidth
5490 | BoxFit::None => false,
5491 }
5492}
5493
5494impl RenderFittedBox {
5495 pub fn new(
5497 app: &mut App,
5498 fit: BoxFit,
5499 alignment: AlignmentGeometry,
5500 text_direction: Option<TextDirection>,
5501 child: Option<AnyRenderBox>,
5502 ) -> RenderHandle<RenderFittedBox> {
5503 let this = RenderHandle::new_box(
5504 app,
5505 RenderFittedBox {
5506 render_object: RenderObjectData::new(),
5507 render_box: RenderBoxData::new(),
5508 child: RenderObjectWithChildData::new(),
5509 fit,
5510 alignment,
5511 text_direction,
5512 resolved_alignment: None,
5513 clip_behavior: Clip::None,
5514 has_visual_overflow: None,
5515 transform: None,
5516 },
5517 );
5518 this.set_child(app, child);
5519 this
5520 }
5521
5522 fn resolve(self: RenderHandle<Self>, app: &mut App) -> Alignment {
5523 let this = self.get(app);
5524 if let Some(resolved) = this.resolved_alignment {
5525 return resolved;
5526 }
5527 let resolved = this.alignment.resolve(this.text_direction);
5528 self.get_mut(app).resolved_alignment = Some(resolved);
5529 resolved
5530 }
5531
5532 fn mark_need_resolution(self: RenderHandle<Self>, app: &mut App) {
5533 self.get_mut(app).resolved_alignment = None;
5534 self.mark_needs_paint(app);
5535 }
5536
5537 pub fn fit(self: RenderHandle<Self>, app: &App) -> BoxFit {
5539 self.get(app).fit
5540 }
5541
5542 pub fn set_fit(self: RenderHandle<Self>, app: &mut App, value: BoxFit) {
5544 let last_fit = self.get(app).fit;
5545 if last_fit == value {
5546 return;
5547 }
5548 self.get_mut(app).fit = value;
5549 if fit_affects_layout(last_fit) || fit_affects_layout(value) {
5550 self.mark_needs_layout(app);
5551 } else {
5552 self.clear_paint_data(app);
5553 self.mark_needs_paint(app);
5554 }
5555 }
5556
5557 pub fn alignment(self: RenderHandle<Self>, app: &App) -> AlignmentGeometry {
5563 self.get(app).alignment
5564 }
5565
5566 pub fn set_alignment(self: RenderHandle<Self>, app: &mut App, value: AlignmentGeometry) {
5568 if self.get(app).alignment == value {
5569 return;
5570 }
5571 self.get_mut(app).alignment = value;
5572 self.clear_paint_data(app);
5573 self.mark_need_resolution(app);
5574 }
5575
5576 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
5578 self.get(app).text_direction
5579 }
5580
5581 pub fn set_text_direction(
5583 self: RenderHandle<Self>,
5584 app: &mut App,
5585 value: Option<TextDirection>,
5586 ) {
5587 if self.get(app).text_direction == value {
5588 return;
5589 }
5590 self.get_mut(app).text_direction = value;
5591 self.clear_paint_data(app);
5592 self.mark_need_resolution(app);
5593 }
5594
5595 pub fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
5597 self.get(app).clip_behavior
5598 }
5599
5600 pub fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
5602 if self.get(app).clip_behavior == value {
5603 return;
5604 }
5605 self.get_mut(app).clip_behavior = value;
5606 self.mark_needs_paint(app);
5607 }
5608
5609 pub fn paints_child(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> bool {
5614 debug_assert_eq!(child.as_object().parent(app), Some(self.as_object()));
5615 !self.size(app).is_empty() && !child.size(app).is_empty()
5616 }
5617
5618 fn clear_paint_data(self: RenderHandle<Self>, app: &mut App) {
5619 let this = self.get_mut(app);
5620 this.has_visual_overflow = None;
5621 this.transform = None;
5622 }
5623
5624 fn paint_data(self: RenderHandle<Self>, app: &App) -> (bool, Matrix4) {
5627 let Some(child) = self.child(app) else {
5628 return (false, Matrix4::IDENTITY);
5629 };
5630 let this = self.get(app);
5631 let resolved_alignment = this
5632 .resolved_alignment
5633 .unwrap_or_else(|| this.alignment.resolve(this.text_direction));
5634 let child_size = child.size(app);
5635 let sizes = apply_box_fit(this.fit, child_size, self.size(app));
5636 let scale_x = sizes.destination.width() / sizes.source.width();
5637 let scale_y = sizes.destination.height() / sizes.source.height();
5638 let source_rect = resolved_alignment.inscribe(sizes.source, Offset::ZERO & child_size);
5639 let destination_rect =
5640 resolved_alignment.inscribe(sizes.destination, Offset::ZERO & self.size(app));
5641 debug_assert!(scale_x.is_finite() && scale_y.is_finite());
5642 let mut transform =
5643 Matrix4::translation(destination_rect.left as f32, destination_rect.top as f32);
5644 crate::object::multiply(
5645 &mut transform,
5646 &Matrix4::scale(scale_x as f32, scale_y as f32),
5647 );
5648 crate::object::translate(&mut transform, -source_rect.left, -source_rect.top);
5649 let has_visual_overflow =
5650 source_rect.width() < child_size.width() || source_rect.height() < child_size.height();
5651 (has_visual_overflow, transform)
5652 }
5653
5654 fn update_paint_data(self: RenderHandle<Self>, app: &mut App) {
5655 if self.get(app).transform.is_some() {
5656 return;
5657 }
5658 self.resolve(app);
5660 let (has_visual_overflow, transform) = self.paint_data(app);
5661 let this = self.get_mut(app);
5662 this.has_visual_overflow = Some(has_visual_overflow);
5663 this.transform = Some(transform);
5664 }
5665
5666 fn paint_child_with_transform(
5667 self: RenderHandle<Self>,
5668 app: &mut App,
5669 context: &mut PaintingContext,
5670 offset: Offset,
5671 ) -> Option<Handle<TransformLayer>> {
5672 let transform = self.get(app).transform.expect("update_paint_data ran");
5673 match get_as_translation(transform) {
5674 Some(child_offset) => {
5675 RenderProxyBoxMixin::paint(self, app, context, offset + child_offset);
5676 None
5677 }
5678 None => context.push_transform(
5679 app,
5680 self.as_object().needs_compositing(app),
5681 offset,
5682 transform,
5683 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
5684 self.as_object().layer_as::<TransformLayer>(app),
5685 ),
5686 }
5687 }
5688}
5689
5690impl RenderObjectWithChildMixin for RenderFittedBox {
5691 type ChildType = AnyRenderBox;
5692
5693 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5694 &self.get(app).child
5695 }
5696
5697 fn child_data_mut(
5698 self: RenderHandle<Self>,
5699 app: &mut App,
5700 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5701 &mut self.get_mut(app).child
5702 }
5703}
5704
5705impl RenderProxyBoxMixin for RenderFittedBox {}
5706
5707impl RenderObject for RenderFittedBox {
5708 crate::render_object_accessors!();
5709
5710 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5711 let constraints = self.constraints(app);
5712 let Some(child) = self.child(app) else {
5713 self.set_size(app, constraints.smallest());
5714 return;
5715 };
5716 child.layout(app, BoxConstraints::new(), true);
5717 let child_size = child.size(app);
5718 let size = match self.fit(app) {
5719 BoxFit::ScaleDown => {
5720 let size_constraints = constraints.loosen();
5721 let unconstrained_size = size_constraints
5722 .constrain_size_and_attempt_to_preserve_aspect_ratio(child_size);
5723 constraints.constrain(unconstrained_size)
5724 }
5725 BoxFit::Contain
5726 | BoxFit::Cover
5727 | BoxFit::Fill
5728 | BoxFit::FitHeight
5729 | BoxFit::FitWidth
5730 | BoxFit::None => {
5731 constraints.constrain_size_and_attempt_to_preserve_aspect_ratio(child_size)
5732 }
5733 };
5734 self.set_size(app, size);
5735 self.clear_paint_data(app);
5736 }
5737
5738 fn paint(
5739 self: RenderHandle<Self>,
5740 app: &mut App,
5741 context: &mut PaintingContext,
5742 offset: Offset,
5743 ) {
5744 let Some(child) = self.child(app) else {
5745 return;
5746 };
5747 if self.size(app).is_empty() || child.size(app).is_empty() {
5748 return;
5749 }
5750 self.update_paint_data(app);
5751 let clip_behavior = self.clip_behavior(app);
5752 if self.get(app).has_visual_overflow == Some(true) && clip_behavior != Clip::None {
5753 let clip_rect = Offset::ZERO & self.size(app);
5754 let old = self.as_object().layer_as::<ClipRectLayer>(app);
5755 let layer = context.push_clip_rect(
5756 app,
5757 self.as_object().needs_compositing(app),
5758 offset,
5759 clip_rect,
5760 |app, context, offset| {
5761 let _ = self.paint_child_with_transform(app, context, offset);
5762 },
5763 clip_behavior,
5764 old,
5765 );
5766 self.as_object()
5767 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5768 } else {
5769 let layer = self.paint_child_with_transform(app, context, offset);
5770 self.as_object()
5771 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5772 }
5773 }
5774
5775 fn visit_children(
5776 self: RenderHandle<Self>,
5777 app: &App,
5778 visitor: &mut dyn FnMut(AnyRenderObject),
5779 ) {
5780 if let Some(child) = self.child(app) {
5781 visitor(child.as_object());
5782 }
5783 }
5784}
5785
5786impl RenderBox for RenderFittedBox {
5787 crate::render_box_accessors!();
5788
5789 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
5790 RenderProxyBoxMixin::setup_parent_data(self, app, child);
5791 }
5792
5793 fn apply_paint_transform(
5794 self: RenderHandle<Self>,
5795 app: &App,
5796 child: AnyRenderObject,
5797 transform: &mut Matrix4,
5798 ) {
5799 let child = child.as_box().expect("a fitted box has a box child");
5800 if !self.paints_child(app, child) {
5801 *transform = crate::object::zero_matrix();
5802 return;
5803 }
5804 let (_, fitted) = self.paint_data(app);
5805 crate::object::multiply(transform, &fitted);
5806 }
5807
5808 fn hit_test_children(
5809 self: RenderHandle<Self>,
5810 app: &mut App,
5811 result: &mut BoxHitTestResult<'_>,
5812 position: Offset,
5813 ) -> bool {
5814 let child_is_empty = self
5815 .child(app)
5816 .is_none_or(|child| child.size(app).is_empty());
5817 if self.size(app).is_empty() || child_is_empty {
5818 return false;
5819 }
5820 self.update_paint_data(app);
5821 let transform = self.get(app).transform;
5822 result.add_with_paint_transform(transform, position, |result, position| {
5823 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5824 })
5825 }
5826
5827 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5828 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5829 }
5830
5831 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5832 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5833 }
5834
5835 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5836 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5837 }
5838
5839 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5840 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5841 }
5842
5843 fn compute_distance_to_actual_baseline(
5844 self: RenderHandle<Self>,
5845 app: &mut App,
5846 baseline: TextBaseline,
5847 ) -> Option<f64> {
5848 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5849 }
5850
5851 fn compute_dry_layout(
5852 self: RenderHandle<Self>,
5853 app: &mut App,
5854 constraints: BoxConstraints,
5855 ) -> Size {
5856 let Some(child) = self.child(app) else {
5857 return constraints.smallest();
5858 };
5859 let child_size = child.get_dry_layout(app, BoxConstraints::new());
5860 match self.fit(app) {
5861 BoxFit::ScaleDown => {
5862 let size_constraints = constraints.loosen();
5863 let unconstrained_size = size_constraints
5864 .constrain_size_and_attempt_to_preserve_aspect_ratio(child_size);
5865 constraints.constrain(unconstrained_size)
5866 }
5867 BoxFit::Contain
5868 | BoxFit::Cover
5869 | BoxFit::Fill
5870 | BoxFit::FitHeight
5871 | BoxFit::FitWidth
5872 | BoxFit::None => {
5873 constraints.constrain_size_and_attempt_to_preserve_aspect_ratio(child_size)
5874 }
5875 }
5876 }
5877
5878 fn compute_dry_baseline(
5879 self: RenderHandle<Self>,
5880 app: &mut App,
5881 _constraints: BoxConstraints,
5882 baseline: TextBaseline,
5883 ) -> Option<f64> {
5884 self.child(app)?
5887 .get_dry_baseline(app, BoxConstraints::new(), baseline)
5888 }
5889}
5890
5891pub struct RenderFractionalTranslation {
5901 render_object: RenderObjectData,
5902 render_box: RenderBoxData,
5903 child: RenderObjectWithChildData<AnyRenderBox>,
5904 translation: Offset,
5905 transform_hit_tests: bool,
5906}
5907
5908impl RenderFractionalTranslation {
5909 pub fn new(
5911 app: &mut App,
5912 translation: Offset,
5913 transform_hit_tests: bool,
5914 child: Option<AnyRenderBox>,
5915 ) -> RenderHandle<RenderFractionalTranslation> {
5916 let this = RenderHandle::new_box(
5917 app,
5918 RenderFractionalTranslation {
5919 render_object: RenderObjectData::new(),
5920 render_box: RenderBoxData::new(),
5921 child: RenderObjectWithChildData::new(),
5922 translation,
5923 transform_hit_tests,
5924 },
5925 );
5926 this.set_child(app, child);
5927 this
5928 }
5929
5930 pub fn translation(self: RenderHandle<Self>, app: &App) -> Offset {
5935 self.get(app).translation
5936 }
5937
5938 pub fn set_translation(self: RenderHandle<Self>, app: &mut App, value: Offset) {
5940 if self.get(app).translation == value {
5941 return;
5942 }
5943 self.get_mut(app).translation = value;
5944 self.mark_needs_paint(app);
5945 }
5946
5947 pub fn transform_hit_tests(self: RenderHandle<Self>, app: &App) -> bool {
5955 self.get(app).transform_hit_tests
5956 }
5957
5958 pub fn set_transform_hit_tests(self: RenderHandle<Self>, app: &mut App, value: bool) {
5960 self.get_mut(app).transform_hit_tests = value;
5961 }
5962
5963 fn absolute_translation(self: RenderHandle<Self>, app: &App) -> Offset {
5965 let translation = self.get(app).translation;
5966 let size = self.size(app);
5967 Offset::new(
5968 translation.dx() * size.width(),
5969 translation.dy() * size.height(),
5970 )
5971 }
5972}
5973
5974impl RenderObjectWithChildMixin for RenderFractionalTranslation {
5975 type ChildType = AnyRenderBox;
5976
5977 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5978 &self.get(app).child
5979 }
5980
5981 fn child_data_mut(
5982 self: RenderHandle<Self>,
5983 app: &mut App,
5984 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5985 &mut self.get_mut(app).child
5986 }
5987}
5988
5989impl RenderProxyBoxMixin for RenderFractionalTranslation {}
5990
5991impl RenderObject for RenderFractionalTranslation {
5992 crate::render_object_accessors!();
5993
5994 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5995 RenderProxyBoxMixin::perform_layout(self, app);
5996 }
5997
5998 fn paint(
5999 self: RenderHandle<Self>,
6000 app: &mut App,
6001 context: &mut PaintingContext,
6002 offset: Offset,
6003 ) {
6004 debug_assert!(!self.debug_needs_layout(app));
6005 if self.child(app).is_none() {
6006 return;
6007 }
6008 let translation = self.absolute_translation(app);
6009 RenderProxyBoxMixin::paint(self, app, context, offset + translation);
6010 }
6011
6012 fn visit_children(
6013 self: RenderHandle<Self>,
6014 app: &App,
6015 visitor: &mut dyn FnMut(AnyRenderObject),
6016 ) {
6017 if let Some(child) = self.child(app) {
6018 visitor(child.as_object());
6019 }
6020 }
6021}
6022
6023impl RenderBox for RenderFractionalTranslation {
6024 crate::render_box_accessors!();
6025
6026 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6027 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6028 }
6029
6030 fn apply_paint_transform(
6031 self: RenderHandle<Self>,
6032 app: &App,
6033 _child: AnyRenderObject,
6034 transform: &mut Matrix4,
6035 ) {
6036 let translation = self.absolute_translation(app);
6037 crate::object::translate(transform, translation.dx(), translation.dy());
6038 }
6039
6040 fn hit_test(
6041 self: RenderHandle<Self>,
6042 app: &mut App,
6043 result: &mut BoxHitTestResult<'_>,
6044 position: Offset,
6045 ) -> bool {
6046 RenderBox::hit_test_children(self, app, result, position)
6051 }
6052
6053 fn hit_test_children(
6054 self: RenderHandle<Self>,
6055 app: &mut App,
6056 result: &mut BoxHitTestResult<'_>,
6057 position: Offset,
6058 ) -> bool {
6059 debug_assert!(!self.debug_needs_layout(app));
6060 let offset = self
6061 .transform_hit_tests(app)
6062 .then(|| self.absolute_translation(app));
6063 result.add_with_paint_offset(offset, position, |result, position| {
6064 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6065 })
6066 }
6067
6068 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6069 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6070 }
6071
6072 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6073 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6074 }
6075
6076 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6077 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6078 }
6079
6080 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6081 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6082 }
6083
6084 fn compute_distance_to_actual_baseline(
6085 self: RenderHandle<Self>,
6086 app: &mut App,
6087 baseline: TextBaseline,
6088 ) -> Option<f64> {
6089 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6090 }
6091
6092 fn compute_dry_baseline(
6093 self: RenderHandle<Self>,
6094 app: &mut App,
6095 constraints: BoxConstraints,
6096 baseline: TextBaseline,
6097 ) -> Option<f64> {
6098 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6099 }
6100
6101 fn compute_dry_layout(
6102 self: RenderHandle<Self>,
6103 app: &mut App,
6104 constraints: BoxConstraints,
6105 ) -> Size {
6106 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6107 }
6108}
6109
6110pub struct RenderIgnorePointer {
6122 render_object: RenderObjectData,
6123 render_box: RenderBoxData,
6124 child: RenderObjectWithChildData<AnyRenderBox>,
6125 ignoring: bool,
6126}
6127
6128impl RenderIgnorePointer {
6129 pub fn new(
6131 app: &mut App,
6132 ignoring: bool,
6133 child: Option<AnyRenderBox>,
6134 ) -> RenderHandle<RenderIgnorePointer> {
6135 let this = RenderHandle::new_box(
6136 app,
6137 RenderIgnorePointer {
6138 render_object: RenderObjectData::new(),
6139 render_box: RenderBoxData::new(),
6140 child: RenderObjectWithChildData::new(),
6141 ignoring,
6142 },
6143 );
6144 this.set_child(app, child);
6145 this
6146 }
6147
6148 pub fn ignoring(self: RenderHandle<Self>, app: &App) -> bool {
6153 self.get(app).ignoring
6154 }
6155
6156 pub fn set_ignoring(self: RenderHandle<Self>, app: &mut App, value: bool) {
6158 if value == self.get(app).ignoring {
6159 return;
6160 }
6161 self.get_mut(app).ignoring = value;
6162 }
6163}
6164
6165impl RenderObjectWithChildMixin for RenderIgnorePointer {
6166 type ChildType = AnyRenderBox;
6167
6168 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6169 &self.get(app).child
6170 }
6171
6172 fn child_data_mut(
6173 self: RenderHandle<Self>,
6174 app: &mut App,
6175 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6176 &mut self.get_mut(app).child
6177 }
6178}
6179
6180impl RenderProxyBoxMixin for RenderIgnorePointer {}
6181
6182impl RenderObject for RenderIgnorePointer {
6183 crate::render_object_accessors!();
6184
6185 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6186 RenderProxyBoxMixin::perform_layout(self, app);
6187 }
6188
6189 fn paint(
6190 self: RenderHandle<Self>,
6191 app: &mut App,
6192 context: &mut PaintingContext,
6193 offset: Offset,
6194 ) {
6195 RenderProxyBoxMixin::paint(self, app, context, offset);
6196 }
6197
6198 fn visit_children(
6199 self: RenderHandle<Self>,
6200 app: &App,
6201 visitor: &mut dyn FnMut(AnyRenderObject),
6202 ) {
6203 if let Some(child) = self.child(app) {
6204 visitor(child.as_object());
6205 }
6206 }
6207}
6208
6209impl RenderBox for RenderIgnorePointer {
6210 crate::render_box_accessors!();
6211
6212 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6213 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6214 }
6215
6216 fn apply_paint_transform(
6217 self: RenderHandle<Self>,
6218 app: &App,
6219 child: AnyRenderObject,
6220 transform: &mut Matrix4,
6221 ) {
6222 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6223 }
6224
6225 fn hit_test(
6226 self: RenderHandle<Self>,
6227 app: &mut App,
6228 result: &mut BoxHitTestResult<'_>,
6229 position: Offset,
6230 ) -> bool {
6231 !self.ignoring(app) && RenderBoxBase::hit_test(self, app, result, position)
6232 }
6233
6234 fn hit_test_children(
6235 self: RenderHandle<Self>,
6236 app: &mut App,
6237 result: &mut BoxHitTestResult<'_>,
6238 position: Offset,
6239 ) -> bool {
6240 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6241 }
6242
6243 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6244 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6245 }
6246
6247 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6248 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6249 }
6250
6251 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6252 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6253 }
6254
6255 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6256 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6257 }
6258
6259 fn compute_distance_to_actual_baseline(
6260 self: RenderHandle<Self>,
6261 app: &mut App,
6262 baseline: TextBaseline,
6263 ) -> Option<f64> {
6264 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6265 }
6266
6267 fn compute_dry_baseline(
6268 self: RenderHandle<Self>,
6269 app: &mut App,
6270 constraints: BoxConstraints,
6271 baseline: TextBaseline,
6272 ) -> Option<f64> {
6273 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6274 }
6275
6276 fn compute_dry_layout(
6277 self: RenderHandle<Self>,
6278 app: &mut App,
6279 constraints: BoxConstraints,
6280 ) -> Size {
6281 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6282 }
6283}
6284
6285pub struct RenderOffstage {
6289 render_object: RenderObjectData,
6290 render_box: RenderBoxData,
6291 child: RenderObjectWithChildData<AnyRenderBox>,
6292 offstage: bool,
6293}
6294
6295impl RenderOffstage {
6296 pub fn new(
6298 app: &mut App,
6299 offstage: bool,
6300 child: Option<AnyRenderBox>,
6301 ) -> RenderHandle<RenderOffstage> {
6302 let this = RenderHandle::new_box(
6303 app,
6304 RenderOffstage {
6305 render_object: RenderObjectData::new(),
6306 render_box: RenderBoxData::new(),
6307 child: RenderObjectWithChildData::new(),
6308 offstage,
6309 },
6310 );
6311 this.set_child(app, child);
6312 this
6313 }
6314
6315 pub fn offstage(self: RenderHandle<Self>, app: &App) -> bool {
6323 self.get(app).offstage
6324 }
6325
6326 pub fn set_offstage(self: RenderHandle<Self>, app: &mut App, value: bool) {
6328 if value == self.get(app).offstage {
6329 return;
6330 }
6331 self.get_mut(app).offstage = value;
6332 self.as_object()
6333 .mark_needs_layout_for_sized_by_parent_change(app);
6334 }
6335
6336 pub fn paints_child(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> bool {
6341 debug_assert_eq!(child.as_object().parent(app), Some(self.as_object()));
6342 !self.get(app).offstage
6343 }
6344}
6345
6346impl RenderObjectWithChildMixin for RenderOffstage {
6347 type ChildType = AnyRenderBox;
6348
6349 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6350 &self.get(app).child
6351 }
6352
6353 fn child_data_mut(
6354 self: RenderHandle<Self>,
6355 app: &mut App,
6356 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6357 &mut self.get_mut(app).child
6358 }
6359}
6360
6361impl RenderProxyBoxMixin for RenderOffstage {}
6362
6363impl RenderObject for RenderOffstage {
6364 crate::render_object_accessors!();
6365
6366 fn sized_by_parent(self: RenderHandle<Self>, app: &App) -> bool {
6367 self.get(app).offstage
6368 }
6369
6370 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6371 if !self.get(app).offstage {
6372 RenderProxyBoxMixin::perform_layout(self, app);
6373 return;
6374 }
6375 if let Some(child) = self.child(app) {
6376 let constraints = self.constraints(app);
6377 child.layout(app, constraints, false);
6378 }
6379 }
6380
6381 fn paint(
6382 self: RenderHandle<Self>,
6383 app: &mut App,
6384 context: &mut PaintingContext,
6385 offset: Offset,
6386 ) {
6387 if self.get(app).offstage {
6388 return;
6389 }
6390 RenderProxyBoxMixin::paint(self, app, context, offset);
6391 }
6392
6393 fn visit_children(
6394 self: RenderHandle<Self>,
6395 app: &App,
6396 visitor: &mut dyn FnMut(AnyRenderObject),
6397 ) {
6398 if let Some(child) = self.child(app) {
6399 visitor(child.as_object());
6400 }
6401 }
6402}
6403
6404impl RenderBox for RenderOffstage {
6405 crate::render_box_accessors!();
6406
6407 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6408 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6409 }
6410
6411 fn apply_paint_transform(
6412 self: RenderHandle<Self>,
6413 app: &App,
6414 child: AnyRenderObject,
6415 transform: &mut Matrix4,
6416 ) {
6417 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6418 }
6419
6420 fn hit_test(
6421 self: RenderHandle<Self>,
6422 app: &mut App,
6423 result: &mut BoxHitTestResult<'_>,
6424 position: Offset,
6425 ) -> bool {
6426 !self.get(app).offstage && RenderBoxBase::hit_test(self, app, result, position)
6427 }
6428
6429 fn hit_test_children(
6430 self: RenderHandle<Self>,
6431 app: &mut App,
6432 result: &mut BoxHitTestResult<'_>,
6433 position: Offset,
6434 ) -> bool {
6435 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6436 }
6437
6438 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6439 if self.get(app).offstage {
6440 return 0.0;
6441 }
6442 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6443 }
6444
6445 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6446 if self.get(app).offstage {
6447 return 0.0;
6448 }
6449 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6450 }
6451
6452 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6453 if self.get(app).offstage {
6454 return 0.0;
6455 }
6456 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6457 }
6458
6459 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6460 if self.get(app).offstage {
6461 return 0.0;
6462 }
6463 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6464 }
6465
6466 fn compute_distance_to_actual_baseline(
6467 self: RenderHandle<Self>,
6468 app: &mut App,
6469 baseline: TextBaseline,
6470 ) -> Option<f64> {
6471 if self.get(app).offstage {
6472 return None;
6473 }
6474 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6475 }
6476
6477 fn compute_dry_baseline(
6478 self: RenderHandle<Self>,
6479 app: &mut App,
6480 constraints: BoxConstraints,
6481 baseline: TextBaseline,
6482 ) -> Option<f64> {
6483 if self.get(app).offstage {
6484 return None;
6485 }
6486 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6487 }
6488
6489 fn compute_dry_layout(
6490 self: RenderHandle<Self>,
6491 app: &mut App,
6492 constraints: BoxConstraints,
6493 ) -> Size {
6494 if self.get(app).offstage {
6495 return constraints.smallest();
6496 }
6497 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6498 }
6499
6500 fn perform_resize(self: RenderHandle<Self>, app: &mut App) {
6502 debug_assert!(self.get(app).offstage);
6503 RenderBoxBase::perform_resize(self, app);
6504 }
6505}
6506
6507pub struct RenderAbsorbPointer {
6520 render_object: RenderObjectData,
6521 render_box: RenderBoxData,
6522 child: RenderObjectWithChildData<AnyRenderBox>,
6523 absorbing: bool,
6524}
6525
6526impl RenderAbsorbPointer {
6527 pub fn new(
6529 app: &mut App,
6530 absorbing: bool,
6531 child: Option<AnyRenderBox>,
6532 ) -> RenderHandle<RenderAbsorbPointer> {
6533 let this = RenderHandle::new_box(
6534 app,
6535 RenderAbsorbPointer {
6536 render_object: RenderObjectData::new(),
6537 render_box: RenderBoxData::new(),
6538 child: RenderObjectWithChildData::new(),
6539 absorbing,
6540 },
6541 );
6542 this.set_child(app, child);
6543 this
6544 }
6545
6546 pub fn absorbing(self: RenderHandle<Self>, app: &App) -> bool {
6552 self.get(app).absorbing
6553 }
6554
6555 pub fn set_absorbing(self: RenderHandle<Self>, app: &mut App, value: bool) {
6557 if self.get(app).absorbing == value {
6558 return;
6559 }
6560 self.get_mut(app).absorbing = value;
6561 }
6562}
6563
6564impl RenderObjectWithChildMixin for RenderAbsorbPointer {
6565 type ChildType = AnyRenderBox;
6566
6567 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6568 &self.get(app).child
6569 }
6570
6571 fn child_data_mut(
6572 self: RenderHandle<Self>,
6573 app: &mut App,
6574 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6575 &mut self.get_mut(app).child
6576 }
6577}
6578
6579impl RenderProxyBoxMixin for RenderAbsorbPointer {}
6580
6581impl RenderObject for RenderAbsorbPointer {
6582 crate::render_object_accessors!();
6583
6584 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6585 RenderProxyBoxMixin::perform_layout(self, app);
6586 }
6587
6588 fn paint(
6589 self: RenderHandle<Self>,
6590 app: &mut App,
6591 context: &mut PaintingContext,
6592 offset: Offset,
6593 ) {
6594 RenderProxyBoxMixin::paint(self, app, context, offset);
6595 }
6596
6597 fn visit_children(
6598 self: RenderHandle<Self>,
6599 app: &App,
6600 visitor: &mut dyn FnMut(AnyRenderObject),
6601 ) {
6602 if let Some(child) = self.child(app) {
6603 visitor(child.as_object());
6604 }
6605 }
6606}
6607
6608impl RenderBox for RenderAbsorbPointer {
6609 crate::render_box_accessors!();
6610
6611 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6612 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6613 }
6614
6615 fn apply_paint_transform(
6616 self: RenderHandle<Self>,
6617 app: &App,
6618 child: AnyRenderObject,
6619 transform: &mut Matrix4,
6620 ) {
6621 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6622 }
6623
6624 fn hit_test(
6625 self: RenderHandle<Self>,
6626 app: &mut App,
6627 result: &mut BoxHitTestResult<'_>,
6628 position: Offset,
6629 ) -> bool {
6630 if self.absorbing(app) {
6631 return self.size(app).contains(position);
6632 }
6633 RenderBoxBase::hit_test(self, app, result, position)
6634 }
6635
6636 fn hit_test_children(
6637 self: RenderHandle<Self>,
6638 app: &mut App,
6639 result: &mut BoxHitTestResult<'_>,
6640 position: Offset,
6641 ) -> bool {
6642 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6643 }
6644
6645 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6646 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6647 }
6648
6649 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6650 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6651 }
6652
6653 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6654 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6655 }
6656
6657 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6658 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6659 }
6660
6661 fn compute_distance_to_actual_baseline(
6662 self: RenderHandle<Self>,
6663 app: &mut App,
6664 baseline: TextBaseline,
6665 ) -> Option<f64> {
6666 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6667 }
6668
6669 fn compute_dry_baseline(
6670 self: RenderHandle<Self>,
6671 app: &mut App,
6672 constraints: BoxConstraints,
6673 baseline: TextBaseline,
6674 ) -> Option<f64> {
6675 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6676 }
6677
6678 fn compute_dry_layout(
6679 self: RenderHandle<Self>,
6680 app: &mut App,
6681 constraints: BoxConstraints,
6682 ) -> Size {
6683 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6684 }
6685}
6686
6687pub struct RenderColoredBox {
6692 render_object: RenderObjectData,
6693 render_box: RenderBoxData,
6694 child: RenderObjectWithChildData<AnyRenderBox>,
6695 color: Color,
6696 is_anti_alias: bool,
6697 behavior: HitTestBehavior,
6698}
6699
6700impl RenderColoredBox {
6701 pub fn new(
6703 app: &mut App,
6704 color: Color,
6705 is_anti_alias: bool,
6706 child: Option<AnyRenderBox>,
6707 ) -> RenderHandle<RenderColoredBox> {
6708 let this = RenderHandle::new_box(
6709 app,
6710 RenderColoredBox {
6711 render_object: RenderObjectData::new(),
6712 render_box: RenderBoxData::new(),
6713 child: RenderObjectWithChildData::new(),
6714 color,
6715 is_anti_alias,
6716 behavior: HitTestBehavior::Opaque,
6717 },
6718 );
6719 this.set_child(app, child);
6720 this
6721 }
6722
6723 pub fn color(self: RenderHandle<Self>, app: &App) -> Color {
6725 self.get(app).color
6726 }
6727
6728 pub fn set_color(self: RenderHandle<Self>, app: &mut App, value: Color) {
6730 if value == self.get(app).color {
6731 return;
6732 }
6733 self.get_mut(app).color = value;
6734 self.mark_needs_paint(app);
6735 }
6736
6737 pub fn is_anti_alias(self: RenderHandle<Self>, app: &App) -> bool {
6739 self.get(app).is_anti_alias
6740 }
6741
6742 pub fn set_is_anti_alias(self: RenderHandle<Self>, app: &mut App, value: bool) {
6744 if value == self.get(app).is_anti_alias {
6745 return;
6746 }
6747 self.get_mut(app).is_anti_alias = value;
6748 self.mark_needs_paint(app);
6749 }
6750}
6751
6752impl RenderObjectWithChildMixin for RenderColoredBox {
6753 type ChildType = AnyRenderBox;
6754
6755 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6756 &self.get(app).child
6757 }
6758
6759 fn child_data_mut(
6760 self: RenderHandle<Self>,
6761 app: &mut App,
6762 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6763 &mut self.get_mut(app).child
6764 }
6765}
6766
6767impl RenderProxyBoxMixin for RenderColoredBox {}
6768
6769impl RenderProxyBoxWithHitTestBehavior for RenderColoredBox {
6770 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
6771 self.get(app).behavior
6772 }
6773}
6774
6775impl RenderObject for RenderColoredBox {
6776 crate::render_object_accessors!();
6777
6778 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6779 RenderProxyBoxMixin::perform_layout(self, app);
6780 }
6781
6782 fn paint(
6783 self: RenderHandle<Self>,
6784 app: &mut App,
6785 context: &mut PaintingContext,
6786 offset: Offset,
6787 ) {
6788 let size = self.size(app);
6793 if size.gt(&Size::ZERO) {
6794 let paint = Paint {
6795 color: self.get(app).color.into(),
6796 ..Paint::default()
6797 };
6798 context.canvas().draw_rect(offset & size, &paint);
6799 }
6800 if let Some(child) = self.child(app) {
6801 context.paint_child(app, child.as_object(), offset);
6802 }
6803 }
6804
6805 fn visit_children(
6806 self: RenderHandle<Self>,
6807 app: &App,
6808 visitor: &mut dyn FnMut(AnyRenderObject),
6809 ) {
6810 if let Some(child) = self.child(app) {
6811 visitor(child.as_object());
6812 }
6813 }
6814}
6815
6816impl RenderBox for RenderColoredBox {
6817 crate::render_box_accessors!();
6818
6819 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6820 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6821 }
6822
6823 fn apply_paint_transform(
6824 self: RenderHandle<Self>,
6825 app: &App,
6826 child: AnyRenderObject,
6827 transform: &mut Matrix4,
6828 ) {
6829 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6830 }
6831
6832 fn hit_test(
6833 self: RenderHandle<Self>,
6834 app: &mut App,
6835 result: &mut BoxHitTestResult<'_>,
6836 position: Offset,
6837 ) -> bool {
6838 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
6839 }
6840
6841 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
6842 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
6843 }
6844
6845 fn hit_test_children(
6846 self: RenderHandle<Self>,
6847 app: &mut App,
6848 result: &mut BoxHitTestResult<'_>,
6849 position: Offset,
6850 ) -> bool {
6851 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6852 }
6853
6854 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6855 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6856 }
6857
6858 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6859 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6860 }
6861
6862 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6863 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6864 }
6865
6866 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6867 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6868 }
6869
6870 fn compute_distance_to_actual_baseline(
6871 self: RenderHandle<Self>,
6872 app: &mut App,
6873 baseline: TextBaseline,
6874 ) -> Option<f64> {
6875 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6876 }
6877
6878 fn compute_dry_baseline(
6879 self: RenderHandle<Self>,
6880 app: &mut App,
6881 constraints: BoxConstraints,
6882 baseline: TextBaseline,
6883 ) -> Option<f64> {
6884 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6885 }
6886
6887 fn compute_dry_layout(
6888 self: RenderHandle<Self>,
6889 app: &mut App,
6890 constraints: BoxConstraints,
6891 ) -> Size {
6892 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6893 }
6894}
6895
6896pub struct RenderMetaData {
6903 render_object: RenderObjectData,
6904 render_box: RenderBoxData,
6905 child: RenderObjectWithChildData<AnyRenderBox>,
6906 meta_data: Option<Rc<dyn Any>>,
6907 behavior: HitTestBehavior,
6908}
6909
6910impl RenderMetaData {
6911 pub fn new(
6915 app: &mut App,
6916 meta_data: Option<Rc<dyn Any>>,
6917 behavior: HitTestBehavior,
6918 child: Option<AnyRenderBox>,
6919 ) -> RenderHandle<Self> {
6920 let this = RenderHandle::new_box(
6921 app,
6922 RenderMetaData {
6923 render_object: RenderObjectData::new(),
6924 render_box: RenderBoxData::new(),
6925 child: RenderObjectWithChildData::new(),
6926 meta_data,
6927 behavior,
6928 },
6929 );
6930 this.set_child(app, child);
6931 this
6932 }
6933
6934 pub fn meta_data(self: RenderHandle<Self>, app: &App) -> Option<Rc<dyn Any>> {
6936 self.get(app).meta_data.clone()
6937 }
6938
6939 pub fn set_meta_data(self: RenderHandle<Self>, app: &mut App, value: Option<Rc<dyn Any>>) {
6941 self.get_mut(app).meta_data = value;
6942 }
6943
6944 pub fn set_behavior(self: RenderHandle<Self>, app: &mut App, value: HitTestBehavior) {
6946 self.get_mut(app).behavior = value;
6947 }
6948}
6949
6950impl RenderObjectWithChildMixin for RenderMetaData {
6951 type ChildType = AnyRenderBox;
6952
6953 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6954 &self.get(app).child
6955 }
6956
6957 fn child_data_mut(
6958 self: RenderHandle<Self>,
6959 app: &mut App,
6960 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6961 &mut self.get_mut(app).child
6962 }
6963}
6964
6965impl RenderProxyBoxMixin for RenderMetaData {}
6966
6967impl RenderProxyBoxWithHitTestBehavior for RenderMetaData {
6968 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
6969 self.get(app).behavior
6970 }
6971}
6972
6973impl RenderObject for RenderMetaData {
6974 crate::render_object_accessors!();
6975
6976 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6977 RenderProxyBoxMixin::perform_layout(self, app);
6978 }
6979
6980 fn paint(
6981 self: RenderHandle<Self>,
6982 app: &mut App,
6983 context: &mut PaintingContext,
6984 offset: Offset,
6985 ) {
6986 RenderProxyBoxMixin::paint(self, app, context, offset);
6987 }
6988
6989 fn visit_children(
6990 self: RenderHandle<Self>,
6991 app: &App,
6992 visitor: &mut dyn FnMut(AnyRenderObject),
6993 ) {
6994 if let Some(child) = self.child(app) {
6995 visitor(child.as_object());
6996 }
6997 }
6998}
6999
7000impl RenderBox for RenderMetaData {
7001 crate::render_box_accessors!();
7002
7003 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7004 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7005 }
7006
7007 fn apply_paint_transform(
7008 self: RenderHandle<Self>,
7009 app: &App,
7010 child: AnyRenderObject,
7011 transform: &mut Matrix4,
7012 ) {
7013 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7014 }
7015
7016 fn hit_test(
7017 self: RenderHandle<Self>,
7018 app: &mut App,
7019 result: &mut BoxHitTestResult<'_>,
7020 position: Offset,
7021 ) -> bool {
7022 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
7023 }
7024
7025 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
7026 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
7027 }
7028
7029 fn hit_test_children(
7030 self: RenderHandle<Self>,
7031 app: &mut App,
7032 result: &mut BoxHitTestResult<'_>,
7033 position: Offset,
7034 ) -> bool {
7035 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7036 }
7037
7038 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7039 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7040 }
7041
7042 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7043 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7044 }
7045
7046 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7047 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7048 }
7049
7050 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7051 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7052 }
7053
7054 fn compute_distance_to_actual_baseline(
7055 self: RenderHandle<Self>,
7056 app: &mut App,
7057 baseline: TextBaseline,
7058 ) -> Option<f64> {
7059 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7060 }
7061
7062 fn compute_dry_baseline(
7063 self: RenderHandle<Self>,
7064 app: &mut App,
7065 constraints: BoxConstraints,
7066 baseline: TextBaseline,
7067 ) -> Option<f64> {
7068 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7069 }
7070
7071 fn compute_dry_layout(
7072 self: RenderHandle<Self>,
7073 app: &mut App,
7074 constraints: BoxConstraints,
7075 ) -> Size {
7076 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7077 }
7078}
7079
7080pub struct RenderBackdropFilter {
7085 render_object: RenderObjectData,
7086 render_box: RenderBoxData,
7087 child: RenderObjectWithChildData<AnyRenderBox>,
7088 filter_config: ImageFilterConfig,
7089 blend_mode: BlendMode,
7090 enabled: bool,
7091 backdrop_key: Option<BackdropKey>,
7092}
7093
7094impl RenderBackdropFilter {
7095 pub fn new(
7099 app: &mut App,
7100 filter_config: ImageFilterConfig,
7101 blend_mode: BlendMode,
7102 enabled: bool,
7103 backdrop_key: Option<BackdropKey>,
7104 child: Option<AnyRenderBox>,
7105 ) -> RenderHandle<Self> {
7106 let this = RenderHandle::new_box(
7107 app,
7108 RenderBackdropFilter {
7109 render_object: RenderObjectData::new(),
7110 render_box: RenderBoxData::new(),
7111 child: RenderObjectWithChildData::new(),
7112 filter_config,
7113 blend_mode,
7114 enabled,
7115 backdrop_key,
7116 },
7117 );
7118 this.set_child(app, child);
7119 this
7120 }
7121
7122 pub fn enabled(self: RenderHandle<Self>, app: &App) -> bool {
7124 self.get(app).enabled
7125 }
7126
7127 pub fn set_enabled(self: RenderHandle<Self>, app: &mut App, value: bool) {
7129 if self.get(app).enabled == value {
7130 return;
7131 }
7132 self.get_mut(app).enabled = value;
7133 self.mark_needs_paint(app);
7134 }
7135
7136 pub fn filter(self: RenderHandle<Self>, app: &App) -> ImageFilter {
7141 self.get(app)
7142 .filter_config
7143 .filter()
7144 .expect(
7145 "This getter should only be called when the filter is assigned via the \
7146 `filter` setter.",
7147 )
7148 .clone()
7149 }
7150
7151 pub fn set_filter(self: RenderHandle<Self>, app: &mut App, value: ImageFilter) {
7153 self.set_filter_config(app, ImageFilterConfig::new(value));
7154 }
7155
7156 pub fn filter_config(self: RenderHandle<Self>, app: &App) -> &ImageFilterConfig {
7158 &self.get(app).filter_config
7159 }
7160
7161 pub fn set_filter_config(self: RenderHandle<Self>, app: &mut App, value: ImageFilterConfig) {
7163 if self.get(app).filter_config == value {
7164 return;
7165 }
7166 self.get_mut(app).filter_config = value;
7167 self.mark_needs_paint(app);
7168 }
7169
7170 pub fn blend_mode(self: RenderHandle<Self>, app: &App) -> BlendMode {
7173 self.get(app).blend_mode
7174 }
7175
7176 pub fn set_blend_mode(self: RenderHandle<Self>, app: &mut App, value: BlendMode) {
7178 if self.get(app).blend_mode == value {
7179 return;
7180 }
7181 self.get_mut(app).blend_mode = value;
7182 self.mark_needs_paint(app);
7183 }
7184
7185 pub fn backdrop_key(self: RenderHandle<Self>, app: &App) -> Option<BackdropKey> {
7187 self.get(app).backdrop_key
7188 }
7189
7190 pub fn set_backdrop_key(self: RenderHandle<Self>, app: &mut App, value: Option<BackdropKey>) {
7192 if self.get(app).backdrop_key == value {
7193 return;
7194 }
7195 self.get_mut(app).backdrop_key = value;
7196 self.mark_needs_paint(app);
7197 }
7198}
7199
7200impl RenderObjectWithChildMixin for RenderBackdropFilter {
7201 type ChildType = AnyRenderBox;
7202
7203 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
7204 &self.get(app).child
7205 }
7206
7207 fn child_data_mut(
7208 self: RenderHandle<Self>,
7209 app: &mut App,
7210 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
7211 &mut self.get_mut(app).child
7212 }
7213}
7214
7215impl RenderProxyBoxMixin for RenderBackdropFilter {}
7216
7217impl RenderObject for RenderBackdropFilter {
7218 crate::render_object_accessors!();
7219
7220 fn always_needs_compositing(self: RenderHandle<Self>, app: &App) -> bool {
7221 self.child(app).is_some()
7222 }
7223
7224 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7225 RenderProxyBoxMixin::perform_layout(self, app);
7226 }
7227
7228 fn paint(
7229 self: RenderHandle<Self>,
7230 app: &mut App,
7231 context: &mut PaintingContext,
7232 offset: Offset,
7233 ) {
7234 if !self.get(app).enabled {
7235 RenderProxyBoxMixin::paint(self, app, context, offset);
7236 return;
7237 }
7238 let bounds = offset & self.size(app);
7239 let effective_filter = self
7240 .get(app)
7241 .filter_config
7242 .resolve(ImageFilterContext { bounds });
7243 if self.child(app).is_some() {
7244 debug_assert!(self.as_object().needs_compositing(app));
7245 let (blend_mode, backdrop_key) = {
7246 let this = self.get(app);
7247 (this.blend_mode, this.backdrop_key)
7248 };
7249 let layer = match self.as_object().layer_as::<BackdropFilterLayer>(app) {
7250 Some(layer) => layer,
7251 None => {
7252 let layer = BackdropFilterLayer::new(app);
7253 self.as_object()
7254 .set_layer(app, Some(layer.as_container_layer()));
7255 layer
7256 }
7257 };
7258 layer.set_filter(app, Some(effective_filter));
7259 layer.set_blend_mode(app, blend_mode);
7260 layer.set_backdrop_key(app, backdrop_key);
7261 context.push_layer(
7262 app,
7263 layer.as_container_layer(),
7264 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
7265 offset,
7266 None,
7267 );
7268 } else {
7269 self.as_object().set_layer(app, None);
7270 }
7271 }
7272
7273 fn visit_children(
7274 self: RenderHandle<Self>,
7275 app: &App,
7276 visitor: &mut dyn FnMut(AnyRenderObject),
7277 ) {
7278 if let Some(child) = self.child(app) {
7279 visitor(child.as_object());
7280 }
7281 }
7282}
7283
7284impl RenderBox for RenderBackdropFilter {
7285 crate::render_box_accessors!();
7286
7287 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7288 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7289 }
7290
7291 fn apply_paint_transform(
7292 self: RenderHandle<Self>,
7293 app: &App,
7294 child: AnyRenderObject,
7295 transform: &mut Matrix4,
7296 ) {
7297 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7298 }
7299
7300 fn hit_test_children(
7301 self: RenderHandle<Self>,
7302 app: &mut App,
7303 result: &mut BoxHitTestResult<'_>,
7304 position: Offset,
7305 ) -> bool {
7306 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7307 }
7308
7309 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7310 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7311 }
7312
7313 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7314 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7315 }
7316
7317 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7318 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7319 }
7320
7321 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7322 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7323 }
7324
7325 fn compute_distance_to_actual_baseline(
7326 self: RenderHandle<Self>,
7327 app: &mut App,
7328 baseline: TextBaseline,
7329 ) -> Option<f64> {
7330 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7331 }
7332
7333 fn compute_dry_baseline(
7334 self: RenderHandle<Self>,
7335 app: &mut App,
7336 constraints: BoxConstraints,
7337 baseline: TextBaseline,
7338 ) -> Option<f64> {
7339 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7340 }
7341
7342 fn compute_dry_layout(
7343 self: RenderHandle<Self>,
7344 app: &mut App,
7345 constraints: BoxConstraints,
7346 ) -> Size {
7347 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7348 }
7349}
7350
7351pub struct RenderAnnotatedRegion<T> {
7356 render_object: RenderObjectData,
7357 render_box: RenderBoxData,
7358 child: RenderObjectWithChildData<AnyRenderBox>,
7359 value: Rc<T>,
7360 sized: bool,
7361 layer_handle: LayerHandle<Handle<AnnotatedRegionLayer>>,
7362}
7363
7364impl<T: PartialEq + 'static> RenderAnnotatedRegion<T> {
7365 pub fn new(
7370 app: &mut App,
7371 value: Rc<T>,
7372 sized: bool,
7373 child: Option<AnyRenderBox>,
7374 ) -> RenderHandle<RenderAnnotatedRegion<T>> {
7375 let this = RenderHandle::new_box(
7376 app,
7377 RenderAnnotatedRegion {
7378 render_object: RenderObjectData::new(),
7379 render_box: RenderBoxData::new(),
7380 child: RenderObjectWithChildData::new(),
7381 value,
7382 sized,
7383 layer_handle: LayerHandle::new(),
7384 },
7385 );
7386 this.set_child(app, child);
7387 this
7388 }
7389
7390 pub fn value(self: RenderHandle<Self>, app: &App) -> Rc<T> {
7393 Rc::clone(&self.get(app).value)
7394 }
7395
7396 pub fn set_value(self: RenderHandle<Self>, app: &mut App, new_value: Rc<T>) {
7398 if *self.get(app).value == *new_value {
7399 return;
7400 }
7401 self.get_mut(app).value = new_value;
7402 self.mark_needs_paint(app);
7403 }
7404
7405 pub fn sized(self: RenderHandle<Self>, app: &App) -> bool {
7407 self.get(app).sized
7408 }
7409
7410 pub fn set_sized(self: RenderHandle<Self>, app: &mut App, value: bool) {
7412 if self.get(app).sized == value {
7413 return;
7414 }
7415 self.get_mut(app).sized = value;
7416 self.mark_needs_paint(app);
7417 }
7418}
7419
7420impl<T: PartialEq + 'static> RenderObjectWithChildMixin for RenderAnnotatedRegion<T> {
7421 type ChildType = AnyRenderBox;
7422
7423 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
7424 &self.get(app).child
7425 }
7426
7427 fn child_data_mut(
7428 self: RenderHandle<Self>,
7429 app: &mut App,
7430 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
7431 &mut self.get_mut(app).child
7432 }
7433}
7434
7435impl<T: PartialEq + 'static> RenderProxyBoxMixin for RenderAnnotatedRegion<T> {}
7436
7437impl<T: PartialEq + 'static> RenderObject for RenderAnnotatedRegion<T> {
7438 crate::render_object_accessors!();
7439
7440 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
7441 true
7442 }
7443
7444 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7445 RenderProxyBoxMixin::perform_layout(self, app);
7446 }
7447
7448 fn paint(
7449 self: RenderHandle<Self>,
7450 app: &mut App,
7451 context: &mut PaintingContext,
7452 offset: Offset,
7453 ) {
7454 let sized = self.sized(app);
7455 let value: Rc<dyn Any> = self.value(app);
7456 let layer = AnnotatedRegionLayer::new(app, value);
7457 if sized {
7458 layer.set_size(app, Some(self.size(app)));
7459 layer.set_offset(app, offset);
7460 }
7461 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).layer_handle, Some(layer));
7462 context.push_layer(
7463 app,
7464 layer.as_container_layer(),
7465 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
7466 offset,
7467 None,
7468 );
7469 }
7470
7471 fn dispose(self: RenderHandle<Self>, app: &mut App) {
7472 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).layer_handle, None);
7473 crate::object::RenderObjectBase::dispose(self, app);
7474 }
7475
7476 fn visit_children(
7477 self: RenderHandle<Self>,
7478 app: &App,
7479 visitor: &mut dyn FnMut(AnyRenderObject),
7480 ) {
7481 if let Some(child) = self.child(app) {
7482 visitor(child.as_object());
7483 }
7484 }
7485}
7486
7487impl<T: PartialEq + 'static> RenderBox for RenderAnnotatedRegion<T> {
7488 crate::render_box_accessors!();
7489
7490 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7491 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7492 }
7493
7494 fn apply_paint_transform(
7495 self: RenderHandle<Self>,
7496 app: &App,
7497 child: AnyRenderObject,
7498 transform: &mut Matrix4,
7499 ) {
7500 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7501 }
7502
7503 fn hit_test_children(
7504 self: RenderHandle<Self>,
7505 app: &mut App,
7506 result: &mut BoxHitTestResult<'_>,
7507 position: Offset,
7508 ) -> bool {
7509 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7510 }
7511
7512 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7513 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7514 }
7515
7516 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7517 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7518 }
7519
7520 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7521 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7522 }
7523
7524 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7525 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7526 }
7527
7528 fn compute_distance_to_actual_baseline(
7529 self: RenderHandle<Self>,
7530 app: &mut App,
7531 baseline: TextBaseline,
7532 ) -> Option<f64> {
7533 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7534 }
7535
7536 fn compute_dry_baseline(
7537 self: RenderHandle<Self>,
7538 app: &mut App,
7539 constraints: BoxConstraints,
7540 baseline: TextBaseline,
7541 ) -> Option<f64> {
7542 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7543 }
7544
7545 fn compute_dry_layout(
7546 self: RenderHandle<Self>,
7547 app: &mut App,
7548 constraints: BoxConstraints,
7549 ) -> Size {
7550 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7551 }
7552}
7553
7554#[cfg(test)]
7555mod tests {
7556 use inset_animation::{k_always_complete_animation, k_always_dismissed_animation};
7557 use inset_embedder::ColorFilter;
7558 use inset_embedder::valo::{self, Op};
7559 use inset_foundation::AppCell;
7560 use inset_foundation::ValueNotifier;
7561 use inset_gestures::HitTestResult;
7562 use inset_painting::BoxDecoration;
7563
7564 use super::*;
7565 use crate::layer::{ErasedLayer, OffsetLayer, PictureLayer};
7566 use crate::pipeline_owner::PipelineOwner;
7567 use inset_embedder::SceneBuilder;
7568
7569 fn sized_box(app: &mut App, size: Size) -> RenderHandle<RenderConstrainedBox> {
7570 RenderConstrainedBox::new(app, BoxConstraints::tight(size), None)
7571 }
7572
7573 struct IntrinsicTestBox {
7576 render_object: RenderObjectData,
7577 render_box: RenderBoxData,
7578 intrinsic: Size,
7579 }
7580
7581 impl RenderObject for IntrinsicTestBox {
7582 crate::render_object_accessors!();
7583
7584 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7585 let intrinsic = self.get(app).intrinsic;
7586 let size = self.constraints(app).constrain(intrinsic);
7587 self.set_size(app, size);
7588 }
7589 }
7590
7591 impl RenderBox for IntrinsicTestBox {
7592 crate::render_box_accessors!();
7593
7594 fn compute_min_intrinsic_width(
7595 self: RenderHandle<Self>,
7596 app: &mut App,
7597 _height: f64,
7598 ) -> f64 {
7599 self.get(app).intrinsic.width()
7600 }
7601
7602 fn compute_max_intrinsic_width(
7603 self: RenderHandle<Self>,
7604 app: &mut App,
7605 _height: f64,
7606 ) -> f64 {
7607 self.get(app).intrinsic.width()
7608 }
7609
7610 fn compute_min_intrinsic_height(
7611 self: RenderHandle<Self>,
7612 app: &mut App,
7613 _width: f64,
7614 ) -> f64 {
7615 self.get(app).intrinsic.height()
7616 }
7617
7618 fn compute_max_intrinsic_height(
7619 self: RenderHandle<Self>,
7620 app: &mut App,
7621 _width: f64,
7622 ) -> f64 {
7623 self.get(app).intrinsic.height()
7624 }
7625
7626 fn compute_dry_layout(
7627 self: RenderHandle<Self>,
7628 app: &mut App,
7629 constraints: BoxConstraints,
7630 ) -> Size {
7631 constraints.constrain(self.get(app).intrinsic)
7632 }
7633 }
7634
7635 fn intrinsic_box(app: &mut App, intrinsic: Size) -> RenderHandle<IntrinsicTestBox> {
7636 RenderHandle::new_box(
7637 app,
7638 IntrinsicTestBox {
7639 render_object: RenderObjectData::new(),
7640 render_box: RenderBoxData::new(),
7641 intrinsic,
7642 },
7643 )
7644 }
7645
7646 fn schedule_root_paint(app: &mut App, node: AnyRenderObject) {
7647 let root = OffsetLayer::new(app, Offset::ZERO);
7648 root.as_layer().attach(app, node.id());
7649 node.schedule_initial_paint(app, root.as_container_layer());
7650 }
7651
7652 fn first_frame(app: &mut App, root: AnyRenderBox) -> Handle<PipelineOwner> {
7654 let owner = PipelineOwner::new(app, None, None);
7655 owner.set_root_node(app, Some(root.as_object()));
7656 root.layout(app, BoxConstraints::tight(Size::new(100.0, 100.0)), false);
7657 schedule_root_paint(app, root.as_object());
7658 owner.flush_compositing_bits(app);
7659 owner.flush_paint(app);
7660 owner
7661 }
7662
7663 fn pump_frame(app: &mut App, owner: Handle<PipelineOwner>) {
7664 owner.flush_layout(app);
7665 owner.flush_compositing_bits(app);
7666 owner.flush_paint(app);
7667 }
7668
7669 #[test]
7672 fn constrained_box_intrinsics_enforce_the_additional_constraints() {
7673 let cell = AppCell::new();
7674 let mut app = cell.borrow_mut();
7675 let child = intrinsic_box(&mut app, Size::new(20.0, 30.0));
7676 let loose = RenderConstrainedBox::new(
7677 &mut app,
7678 BoxConstraints::new().min_width(50.0).max_width(60.0),
7679 Some(child.as_box()),
7680 );
7681 assert_eq!(loose.as_box().get_min_intrinsic_width(&mut app, 0.0), 50.0);
7682 assert_eq!(loose.as_box().get_max_intrinsic_width(&mut app, 0.0), 50.0);
7683 assert_eq!(loose.as_box().get_min_intrinsic_height(&mut app, 0.0), 30.0);
7684
7685 let child = intrinsic_box(&mut app, Size::new(20.0, 30.0));
7686 let tight = RenderConstrainedBox::new(
7687 &mut app,
7688 BoxConstraints::tight(Size::new(80.0, 90.0)),
7689 Some(child.as_box()),
7690 );
7691 assert_eq!(tight.as_box().get_max_intrinsic_width(&mut app, 0.0), 80.0);
7692 assert_eq!(tight.as_box().get_max_intrinsic_height(&mut app, 0.0), 90.0);
7693 }
7694
7695 #[test]
7698 fn intrinsic_width_sizes_the_child_to_its_max_intrinsic_width() {
7699 let cell = AppCell::new();
7700 let mut app = cell.borrow_mut();
7701 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7702 let intrinsic = RenderIntrinsicWidth::new(&mut app, None, None, Some(child.as_box()));
7703 intrinsic.layout(&mut app, BoxConstraints::new().max_width(500.0), false);
7704 assert_eq!(intrinsic.size(&app), Size::new(100.0, 40.0));
7705 assert_eq!(child.size(&app), Size::new(100.0, 40.0));
7706
7707 intrinsic.set_step_width(&mut app, Some(30.0));
7708 intrinsic.layout(&mut app, BoxConstraints::new().max_width(500.0), false);
7709 assert_eq!(intrinsic.size(&app), Size::new(120.0, 40.0));
7710 }
7711
7712 #[test]
7714 fn intrinsic_width_dry_layout_matches_its_layout() {
7715 let cell = AppCell::new();
7716 let mut app = cell.borrow_mut();
7717 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7718 let intrinsic = RenderIntrinsicWidth::new(&mut app, None, None, Some(child.as_box()));
7719 let constraints = BoxConstraints::new().max_width(500.0);
7720 let dry = intrinsic.as_box().get_dry_layout(&mut app, constraints);
7721 intrinsic.layout(&mut app, constraints, false);
7722 assert_eq!(dry, intrinsic.size(&app));
7723 }
7724
7725 #[test]
7727 fn intrinsic_height_sizes_the_child_to_its_max_intrinsic_height() {
7728 let cell = AppCell::new();
7729 let mut app = cell.borrow_mut();
7730 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7731 let intrinsic = RenderIntrinsicHeight::new(&mut app, Some(child.as_box()));
7732 intrinsic.layout(&mut app, BoxConstraints::new().max_height(500.0), false);
7733 assert_eq!(intrinsic.size(&app), Size::new(100.0, 40.0));
7734 assert_eq!(
7735 intrinsic
7736 .as_box()
7737 .get_max_intrinsic_width(&mut app, f64::INFINITY),
7738 100.0
7739 );
7740 }
7741
7742 #[test]
7745 fn fitted_box_scales_its_child_into_itself() {
7746 let cell = AppCell::new();
7747 let mut app = cell.borrow_mut();
7748 let child = sized_box(&mut app, Size::new(100.0, 100.0));
7749 let fitted = RenderFittedBox::new(
7750 &mut app,
7751 BoxFit::Contain,
7752 AlignmentGeometry::CENTER,
7753 None,
7754 Some(child.as_box()),
7755 );
7756 fitted.layout(
7757 &mut app,
7758 BoxConstraints::tight(Size::new(50.0, 50.0)),
7759 false,
7760 );
7761 assert_eq!(fitted.size(&app), Size::new(50.0, 50.0));
7762 assert_eq!(child.size(&app), Size::new(100.0, 100.0));
7763
7764 let mut transform = Matrix4::IDENTITY;
7765 RenderBox::apply_paint_transform(fitted, &app, child.as_object(), &mut transform);
7766 assert_eq!(
7767 inset_painting::transform_point(&transform, Offset::new(100.0, 100.0)),
7768 Offset::new(50.0, 50.0)
7769 );
7770 }
7771
7772 #[test]
7775 fn aspect_ratio_sizes_itself_from_the_width() {
7776 let cell = AppCell::new();
7777 let mut app = cell.borrow_mut();
7778 let child = sized_box(&mut app, Size::new(10.0, 10.0));
7779 let aspect = RenderAspectRatio::new(&mut app, 2.0, Some(child.as_box()));
7780 aspect.layout(
7781 &mut app,
7782 BoxConstraints::new().max_width(200.0).max_height(200.0),
7783 false,
7784 );
7785 assert_eq!(aspect.size(&app), Size::new(200.0, 100.0));
7786 assert_eq!(child.size(&app), Size::new(200.0, 100.0));
7787 assert_eq!(
7788 aspect.as_box().get_min_intrinsic_width(&mut app, 50.0),
7789 100.0
7790 );
7791 assert_eq!(
7792 aspect.as_box().get_min_intrinsic_height(&mut app, 50.0),
7793 25.0
7794 );
7795 }
7796
7797 #[test]
7799 fn aspect_ratio_infers_the_width_from_an_unbounded_axis() {
7800 let cell = AppCell::new();
7801 let mut app = cell.borrow_mut();
7802 let aspect = RenderAspectRatio::new(&mut app, 0.5, None);
7803 aspect.layout(&mut app, BoxConstraints::new().max_height(100.0), false);
7804 assert_eq!(aspect.size(&app), Size::new(50.0, 100.0));
7805 }
7806
7807 #[test]
7808 fn constrained_box_without_child() {
7809 let cell = AppCell::new();
7810 let mut app = cell.borrow_mut();
7811 let box_ =
7812 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
7813 box_.layout(&mut app, BoxConstraints::new(), false);
7814 assert_eq!(box_.size(&app), Size::new(80.0, 40.0));
7815 }
7816
7817 #[test]
7818 fn additional_constraints_change_marks_layout() {
7819 let cell = AppCell::new();
7820 let mut app = cell.borrow_mut();
7821 let box_ =
7822 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(10.0, 10.0)), None);
7823 box_.layout(&mut app, BoxConstraints::new(), false);
7824 assert!(!box_.debug_needs_layout(&app));
7825 box_.set_additional_constraints(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)));
7826 assert!(box_.debug_needs_layout(&app));
7827 box_.layout(&mut app, BoxConstraints::new(), false);
7828 assert_eq!(box_.size(&app), Size::new(20.0, 20.0));
7829 }
7830
7831 #[test]
7833 fn proxy_box_child_gets_empty_parent_data() {
7834 let cell = AppCell::new();
7835 let mut app = cell.borrow_mut();
7836 let child = sized_box(&mut app, Size::new(10.0, 10.0));
7837 let parent = RenderConstrainedBox::new(
7838 &mut app,
7839 BoxConstraints::tight(Size::new(10.0, 10.0)),
7840 Some(child.as_box()),
7841 );
7842 parent.layout(&mut app, BoxConstraints::new(), false);
7843 assert!(child.as_box().parent_data_is::<EmptyParentData>(&app));
7844 }
7845
7846 #[test]
7849 fn render_opacity_composites_only_when_visible() {
7850 let cell = AppCell::new();
7851 let mut app = cell.borrow_mut();
7852 for (opacity, composites) in [(0.0, false), (1.0, true), (0.1, true)] {
7853 let child = sized_box(&mut app, Size::new(1.0, 1.0));
7854 let opacity = RenderOpacity::new(&mut app, opacity, Some(child.as_box()));
7855 assert_eq!(opacity.as_object().is_repaint_boundary(&app), composites);
7856 }
7857 }
7858
7859 #[test]
7861 fn non_painted_layers_are_detached() {
7862 let cell = AppCell::new();
7863 let mut app = cell.borrow_mut();
7864 let inner = RenderDecoratedBox::new(
7865 &mut app,
7866 Box::new(BoxDecoration::new()),
7867 DecorationPosition::Background,
7868 ImageConfiguration::EMPTY,
7869 None,
7870 );
7871 let boundary = RenderRepaintBoundary::new(&mut app, Some(inner.as_box()));
7872 let opacity = RenderOpacity::new(&mut app, 1.0, Some(boundary.as_box()));
7873 let root = RenderRepaintBoundary::new(&mut app, Some(opacity.as_box()));
7875 let owner = first_frame(&mut app, root.as_box());
7876 assert!(!inner.as_object().is_repaint_boundary(&app));
7877 assert!(inner.as_object().debug_layer(&app).is_none());
7878 assert!(boundary.as_object().is_repaint_boundary(&app));
7879 let layer = boundary.as_object().debug_layer(&app).expect("painted");
7880 assert!(layer.as_layer().attached(&app), "this time it painted");
7881
7882 opacity.set_opacity(&mut app, 0.0);
7883 pump_frame(&mut app, owner);
7884 assert!(inner.as_object().debug_layer(&app).is_none());
7885 let layer = boundary.as_object().debug_layer(&app).expect("kept");
7886 assert!(!layer.as_layer().attached(&app), "this time it did not");
7887
7888 opacity.set_opacity(&mut app, 0.5);
7889 pump_frame(&mut app, owner);
7890 let layer = boundary.as_object().debug_layer(&app).expect("kept");
7891 assert!(layer.as_layer().attached(&app), "this time it did again");
7892 }
7893
7894 #[test]
7895 fn animated_opacity_follows_its_animation() {
7896 let cell = AppCell::new();
7897 let mut app = cell.borrow_mut();
7898 let child = sized_box(&mut app, Size::new(1.0, 1.0));
7899 let dismissed = k_always_dismissed_animation(&mut app);
7900 let complete = k_always_complete_animation(&mut app);
7901 let fade = RenderAnimatedOpacity::new(&mut app, dismissed, Some(child.as_box()));
7902 assert!(!fade.as_object().is_repaint_boundary(&app));
7903 let root = RenderRepaintBoundary::new(&mut app, Some(fade.as_box()));
7904 let owner = first_frame(&mut app, root.as_box());
7905
7906 fade.set_opacity(&mut app, complete);
7907 assert!(fade.as_object().is_repaint_boundary(&app));
7908 assert!(fade.as_object().debug_needs_paint(&app));
7909 pump_frame(&mut app, owner);
7910 let layer = fade.as_object().debug_layer(&app).expect("a boundary now");
7911 let opacity = app
7912 .handle::<OpacityLayer>(layer.id())
7913 .expect("an OpacityLayer");
7914 assert_eq!(opacity.alpha(&app), Some(255));
7915 }
7916
7917 #[test]
7918 fn decorated_box_paints_its_decoration() {
7919 let cell = AppCell::new();
7920 let mut app = cell.borrow_mut();
7921 let decorated = RenderDecoratedBox::new(
7922 &mut app,
7923 Box::new(BoxDecoration::new().color(Color::from_argb(255, 255, 0, 0))),
7924 DecorationPosition::Background,
7925 ImageConfiguration::EMPTY,
7926 None,
7927 );
7928 let root = RenderRepaintBoundary::new(&mut app, Some(decorated.as_box()));
7929 first_frame(&mut app, root.as_box());
7930 let ops = scene_ops(&mut app, root.as_object());
7931 assert!(
7932 ops.iter()
7933 .any(|op| matches!(op, inset_embedder::valo::Op::DrawDisplayList { .. })),
7934 "{ops:?}"
7935 );
7936 }
7937
7938 fn opaque_leaf(app: &mut App) -> RenderHandle<RenderPointerListener> {
7940 RenderPointerListener::new(app, HitTestBehavior::Opaque, None)
7941 }
7942
7943 const RED: Color = Color::from_argb(255, 255, 0, 0);
7944 const BLUE: Color = Color::from_argb(255, 0, 0, 255);
7945
7946 fn red_box(app: &mut App) -> RenderHandle<RenderColoredBox> {
7947 RenderColoredBox::new(app, RED, true, None)
7948 }
7949
7950 fn hit_test(app: &mut App, target: AnyRenderBox, position: Offset) -> (bool, usize) {
7952 let mut result = HitTestResult::new();
7953 let is_hit = target.hit_test(app, &mut BoxHitTestResult::wrap(&mut result), position);
7954 (is_hit, result.path().len())
7955 }
7956
7957 fn picture_ops(app: &App, boundary: AnyRenderObject) -> Vec<Op> {
7959 let layer = boundary.debug_layer(app).expect("painted");
7960 layer
7961 .depth_first_iterate_children(app)
7962 .into_iter()
7963 .filter_map(|child| {
7964 app.handle::<PictureLayer>(child.id())
7965 .and_then(|picture| picture.picture(app).map(|p| p.ops().to_vec()))
7966 })
7967 .flatten()
7968 .collect()
7969 }
7970
7971 fn picture_has_clip(app: &App, boundary: AnyRenderObject) -> bool {
7972 picture_ops(app, boundary)
7973 .iter()
7974 .any(|op| matches!(op, Op::ClipPath { .. }))
7975 }
7976
7977 fn drawn_rects(app: &App, boundary: AnyRenderObject) -> Vec<(valo::Rect, valo::Color)> {
7979 picture_ops(app, boundary)
7980 .iter()
7981 .filter_map(|op| match op {
7982 Op::DrawRect { rect, paint, .. } => Some((*rect, paint.color)),
7983 _ => None,
7984 })
7985 .collect()
7986 }
7987
7988 fn fill(rect: Rect, color: Color) -> (valo::Rect, valo::Color) {
7989 (rect.into(), color.into())
7990 }
7991
7992 #[test]
7993 fn limited_box_limits_only_unbounded_constraints() {
7994 let cell = AppCell::new();
7995 let mut app = cell.borrow_mut();
7996 let child = opaque_leaf(&mut app);
7997 let limited = RenderLimitedBox::new(&mut app, 100.0, 50.0, Some(child.as_box()));
7998
7999 limited.layout(&mut app, BoxConstraints::new(), false);
8000 assert_eq!(limited.size(&app), Size::new(100.0, 50.0));
8001
8002 limited.layout(
8003 &mut app,
8004 BoxConstraints::loose(Size::new(30.0, 30.0)),
8005 false,
8006 );
8007 assert_eq!(
8008 limited.size(&app),
8009 Size::new(30.0, 30.0),
8010 "a bounded constraint is left alone"
8011 );
8012 }
8013
8014 #[test]
8015 fn limited_box_without_child_is_empty() {
8016 let cell = AppCell::new();
8017 let mut app = cell.borrow_mut();
8018 let limited = RenderLimitedBox::new(&mut app, 100.0, 50.0, None);
8019 limited.layout(&mut app, BoxConstraints::new(), false);
8020 assert_eq!(limited.size(&app), Size::ZERO);
8021 }
8022
8023 struct LeftHalfClipper;
8025
8026 impl CustomClipper<Rect> for LeftHalfClipper {
8027 fn get_clip(&self, size: Size) -> Rect {
8028 Rect::from_ltwh(0.0, 0.0, size.width() / 2.0, size.height())
8029 }
8030
8031 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<Rect>) -> bool {
8032 false
8033 }
8034
8035 fn as_any(&self) -> &dyn Any {
8036 self
8037 }
8038 }
8039
8040 impl CustomClipper<RRect> for LeftHalfClipper {
8041 fn get_clip(&self, size: Size) -> RRect {
8042 RRect::from_rect_xy(
8043 Rect::from_ltwh(0.0, 0.0, size.width() / 2.0, size.height()),
8044 0.0,
8045 0.0,
8046 )
8047 }
8048
8049 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<RRect>) -> bool {
8050 false
8051 }
8052
8053 fn as_any(&self) -> &dyn Any {
8054 self
8055 }
8056 }
8057
8058 struct NotifyingClipper {
8060 reclip: Rc<dyn Listenable>,
8061 }
8062
8063 impl CustomClipper<Rect> for NotifyingClipper {
8064 fn reclip(&self) -> Option<&Rc<dyn Listenable>> {
8065 Some(&self.reclip)
8066 }
8067
8068 fn get_clip(&self, size: Size) -> Rect {
8069 Offset::ZERO & size
8070 }
8071
8072 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<Rect>) -> bool {
8073 false
8074 }
8075
8076 fn as_any(&self) -> &dyn Any {
8077 self
8078 }
8079 }
8080
8081 #[test]
8082 fn clip_rect_pushes_its_clipper_and_clips_hit_tests() {
8083 let cell = AppCell::new();
8084 let mut app = cell.borrow_mut();
8085 let child = opaque_leaf(&mut app);
8086 let clipper: Rc<dyn CustomClipper<Rect>> = Rc::new(LeftHalfClipper);
8087 let clip = RenderClipRect::new(
8088 &mut app,
8089 Some(clipper),
8090 Clip::HardEdge,
8091 Some(child.as_box()),
8092 );
8093 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8094 first_frame(&mut app, root.as_box());
8095
8096 let ops = picture_ops(&app, root.as_object());
8097 let clip_path = ops
8098 .iter()
8099 .find_map(|op| match op {
8100 Op::ClipPath { path, .. } => Some(path),
8101 _ => None,
8102 })
8103 .expect("the recording clips");
8104 assert_eq!(
8105 clip_path.bounds(),
8106 Rect::from_ltwh(0.0, 0.0, 50.0, 100.0).into()
8107 );
8108
8109 assert!(hit_test(&mut app, clip.as_box(), Offset::new(25.0, 50.0)).0);
8110 assert!(
8111 !hit_test(&mut app, clip.as_box(), Offset::new(75.0, 50.0)).0,
8112 "outside the clipper's clip"
8113 );
8114 }
8115
8116 #[test]
8117 fn clip_rect_without_clipping_paints_its_child_directly() {
8118 let cell = AppCell::new();
8119 let mut app = cell.borrow_mut();
8120 let child = red_box(&mut app);
8121 let clip = RenderClipRect::new(&mut app, None, Clip::None, Some(child.as_box()));
8122 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8123 first_frame(&mut app, root.as_box());
8124
8125 assert!(
8126 !picture_has_clip(&app, root.as_object()),
8127 "Clip::None paints the child directly"
8128 );
8129 assert_eq!(
8130 drawn_rects(&app, root.as_object()),
8131 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8132 );
8133 }
8134
8135 #[test]
8136 fn clip_rrect_pushes_its_border_radius() {
8137 let cell = AppCell::new();
8138 let mut app = cell.borrow_mut();
8139 let child = opaque_leaf(&mut app);
8140 let clip = RenderClipRRect::new(
8141 &mut app,
8142 BorderRadiusGeometry::circular(20.0),
8143 None,
8144 Clip::AntiAlias,
8145 None,
8146 Some(child.as_box()),
8147 );
8148 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8149 first_frame(&mut app, root.as_box());
8150
8151 let bounds = Rect::from_ltwh(0.0, 0.0, 100.0, 100.0);
8152 let ops = picture_ops(&app, root.as_object());
8153 let clip_path = ops
8154 .iter()
8155 .find_map(|op| match op {
8156 Op::ClipPath { path, .. } => Some(path),
8157 _ => None,
8158 })
8159 .expect("the recording starts with the clip");
8160 assert_eq!(clip_path.bounds(), bounds.into());
8161
8162 assert!(
8163 hit_test(&mut app, clip.as_box(), Offset::new(99.0, 99.0)).0,
8164 "without a clipper the hit test is not clipped, as in Dart"
8165 );
8166 }
8167
8168 #[test]
8169 fn clip_rrect_clips_hit_tests_to_its_clipper() {
8170 let cell = AppCell::new();
8171 let mut app = cell.borrow_mut();
8172 let child = opaque_leaf(&mut app);
8173 let clipper: Rc<dyn CustomClipper<RRect>> = Rc::new(LeftHalfClipper);
8174 let clip = RenderClipRRect::new(
8175 &mut app,
8176 BorderRadiusGeometry::ZERO,
8177 Some(clipper),
8178 Clip::AntiAlias,
8179 None,
8180 Some(child.as_box()),
8181 );
8182 clip.layout(
8183 &mut app,
8184 BoxConstraints::tight(Size::new(100.0, 100.0)),
8185 false,
8186 );
8187
8188 assert!(hit_test(&mut app, clip.as_box(), Offset::new(25.0, 50.0)).0);
8189 assert!(!hit_test(&mut app, clip.as_box(), Offset::new(75.0, 50.0)).0);
8190 }
8191
8192 #[test]
8194 fn clip_rect_reclips_on_notification_and_on_resize() {
8195 let cell = AppCell::new();
8196 let mut app = cell.borrow_mut();
8197 let reclip = app.create(ValueNotifier::new(0));
8198 let clipper: Rc<dyn CustomClipper<Rect>> = Rc::new(NotifyingClipper {
8199 reclip: Rc::new(reclip),
8200 });
8201 let child = red_box(&mut app);
8202 let clip = RenderClipRect::new(
8203 &mut app,
8204 Some(clipper),
8205 Clip::HardEdge,
8206 Some(child.as_box()),
8207 );
8208 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8209 let owner = first_frame(&mut app, root.as_box());
8210 assert!(clip.custom_clip_data(&app).clip.is_some());
8211
8212 reclip.set_value(&mut app, 1);
8213 assert!(
8214 clip.custom_clip_data(&app).clip.is_none(),
8215 "the clipper's notification dropped the cached clip"
8216 );
8217 assert!(clip.as_object().debug_needs_paint(&app));
8218 pump_frame(&mut app, owner);
8219 assert!(clip.custom_clip_data(&app).clip.is_some());
8220
8221 clip.layout(
8222 &mut app,
8223 BoxConstraints::tight(Size::new(50.0, 50.0)),
8224 false,
8225 );
8226 assert!(
8227 clip.custom_clip_data(&app).clip.is_none(),
8228 "a new size dropped the cached clip"
8229 );
8230 }
8231
8232 #[test]
8233 fn transform_paints_under_its_matrix() {
8234 let cell = AppCell::new();
8235 let mut app = cell.borrow_mut();
8236 let child = red_box(&mut app);
8237 let transform = RenderTransform::new(
8238 &mut app,
8239 Matrix4::scale(2.0, 2.0),
8240 None,
8241 None,
8242 None,
8243 true,
8244 Some(child.as_box()),
8245 );
8246 let root = RenderRepaintBoundary::new(&mut app, Some(transform.as_box()));
8247 first_frame(&mut app, root.as_box());
8248
8249 let ops = picture_ops(&app, root.as_object());
8250 let pushed = ops.iter().find_map(|op| match op {
8251 Op::Transform(transform) => Some(*transform),
8252 _ => None,
8253 });
8254 assert_eq!(pushed, Some(Matrix4::scale(2.0, 2.0)));
8255 }
8256
8257 #[test]
8259 fn transform_by_a_translation_paints_at_an_offset() {
8260 let cell = AppCell::new();
8261 let mut app = cell.borrow_mut();
8262 let child = red_box(&mut app);
8263 let transform = RenderTransform::new(
8264 &mut app,
8265 Matrix4::translation(10.0, 20.0),
8266 None,
8267 None,
8268 None,
8269 true,
8270 Some(child.as_box()),
8271 );
8272 let root = RenderRepaintBoundary::new(&mut app, Some(transform.as_box()));
8273 first_frame(&mut app, root.as_box());
8274
8275 assert!(
8276 !picture_ops(&app, root.as_object())
8277 .iter()
8278 .any(|op| matches!(op, Op::Transform(_))),
8279 "a translation is folded into the child's paint offset"
8280 );
8281 assert_eq!(
8282 drawn_rects(&app, root.as_object()),
8283 [fill(Rect::from_ltwh(10.0, 20.0, 100.0, 100.0), RED)]
8284 );
8285 }
8286
8287 #[test]
8288 fn transform_hit_tests_through_its_matrix() {
8289 let cell = AppCell::new();
8290 let mut app = cell.borrow_mut();
8291 let child = opaque_leaf(&mut app);
8292 let transform = RenderTransform::new(
8293 &mut app,
8294 Matrix4::scale(2.0, 2.0),
8295 None,
8296 None,
8297 None,
8298 true,
8299 Some(child.as_box()),
8300 );
8301 transform.layout(
8302 &mut app,
8303 BoxConstraints::tight(Size::new(100.0, 100.0)),
8304 false,
8305 );
8306
8307 assert_eq!(
8308 hit_test(&mut app, transform.as_box(), Offset::new(150.0, 50.0)),
8309 (true, 1),
8310 "the child covers twice the box, and the transform does not add itself"
8311 );
8312
8313 transform.set_transform_hit_tests(&mut app, false);
8314 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(150.0, 50.0)).0);
8315 assert!(hit_test(&mut app, transform.as_box(), Offset::new(50.0, 50.0)).0);
8316 }
8317
8318 #[test]
8320 fn transform_scales_around_its_alignment_and_origin() {
8321 let cell = AppCell::new();
8322 let mut app = cell.borrow_mut();
8323 let child = opaque_leaf(&mut app);
8324 let transform = RenderTransform::new(
8325 &mut app,
8326 Matrix4::scale(2.0, 2.0),
8327 None,
8328 Some(AlignmentGeometry::CENTER),
8329 None,
8330 true,
8331 Some(child.as_box()),
8332 );
8333 transform.layout(
8334 &mut app,
8335 BoxConstraints::tight(Size::new(100.0, 100.0)),
8336 false,
8337 );
8338 assert!(hit_test(&mut app, transform.as_box(), Offset::new(140.0, 140.0)).0);
8339 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(160.0, 160.0)).0);
8340
8341 transform.set_alignment(&mut app, None);
8342 transform.set_origin(&mut app, Some(Offset::new(50.0, 50.0)));
8343 assert!(
8344 hit_test(&mut app, transform.as_box(), Offset::new(140.0, 140.0)).0,
8345 "an origin at the centre is the same conjugation"
8346 );
8347 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(160.0, 160.0)).0);
8348 }
8349
8350 #[test]
8351 fn transform_applies_its_paint_transform_to_the_child() {
8352 let cell = AppCell::new();
8353 let mut app = cell.borrow_mut();
8354 let child = opaque_leaf(&mut app);
8355 let transform = RenderTransform::new(
8356 &mut app,
8357 Matrix4::translation(10.0, 20.0),
8358 None,
8359 None,
8360 None,
8361 true,
8362 Some(child.as_box()),
8363 );
8364 let mut matrix = Matrix4::IDENTITY;
8365 RenderBox::apply_paint_transform(transform, &app, child.as_object(), &mut matrix);
8366 assert_eq!(matrix, Matrix4::translation(10.0, 20.0));
8367 }
8368
8369 #[test]
8370 fn fractional_translation_offsets_paint_and_hits() {
8371 let cell = AppCell::new();
8372 let mut app = cell.borrow_mut();
8373 let child = red_box(&mut app);
8374 let translated = RenderFractionalTranslation::new(
8375 &mut app,
8376 Offset::new(0.5, 0.0),
8377 true,
8378 Some(child.as_box()),
8379 );
8380 let root = RenderRepaintBoundary::new(&mut app, Some(translated.as_box()));
8381 first_frame(&mut app, root.as_box());
8382
8383 assert_eq!(
8384 drawn_rects(&app, root.as_object()),
8385 [fill(Rect::from_ltwh(50.0, 0.0, 100.0, 100.0), RED)],
8386 "half the width to the right"
8387 );
8388
8389 assert!(hit_test(&mut app, translated.as_box(), Offset::new(75.0, 50.0)).0);
8390 assert!(!hit_test(&mut app, translated.as_box(), Offset::new(25.0, 50.0)).0);
8391
8392 translated.set_transform_hit_tests(&mut app, false);
8393 assert!(
8394 hit_test(&mut app, translated.as_box(), Offset::new(25.0, 50.0)).0,
8395 "an untransformed hit test reaches the child where it was laid out"
8396 );
8397 }
8398
8399 #[test]
8400 fn ignore_pointer_is_invisible_to_hit_testing() {
8401 let cell = AppCell::new();
8402 let mut app = cell.borrow_mut();
8403 let child = opaque_leaf(&mut app);
8404 let ignoring = RenderIgnorePointer::new(&mut app, true, Some(child.as_box()));
8405 ignoring.layout(
8406 &mut app,
8407 BoxConstraints::tight(Size::new(100.0, 100.0)),
8408 false,
8409 );
8410
8411 assert_eq!(
8412 hit_test(&mut app, ignoring.as_box(), Offset::new(50.0, 50.0)),
8413 (false, 0)
8414 );
8415
8416 ignoring.set_ignoring(&mut app, false);
8417 assert_eq!(
8418 hit_test(&mut app, ignoring.as_box(), Offset::new(50.0, 50.0)),
8419 (true, 2),
8420 "the child and the ignore pointer itself"
8421 );
8422 }
8423
8424 #[test]
8425 fn absorb_pointer_takes_the_hit_from_its_subtree() {
8426 let cell = AppCell::new();
8427 let mut app = cell.borrow_mut();
8428 let child = opaque_leaf(&mut app);
8429 let absorbing = RenderAbsorbPointer::new(&mut app, true, Some(child.as_box()));
8430 absorbing.layout(
8431 &mut app,
8432 BoxConstraints::tight(Size::new(100.0, 100.0)),
8433 false,
8434 );
8435
8436 assert_eq!(
8437 hit_test(&mut app, absorbing.as_box(), Offset::new(50.0, 50.0)),
8438 (true, 0),
8439 "hit testing stops here, and nothing is added to the path"
8440 );
8441 assert_eq!(
8442 hit_test(&mut app, absorbing.as_box(), Offset::new(150.0, 50.0)),
8443 (false, 0)
8444 );
8445
8446 absorbing.set_absorbing(&mut app, false);
8447 assert_eq!(
8448 hit_test(&mut app, absorbing.as_box(), Offset::new(50.0, 50.0)),
8449 (true, 2)
8450 );
8451 }
8452
8453 #[test]
8454 fn offstage_lays_out_without_painting_or_hit_testing() {
8455 let cell = AppCell::new();
8456 let mut app = cell.borrow_mut();
8457 let child = red_box(&mut app);
8458 let offstage = RenderOffstage::new(&mut app, true, Some(child.as_box()));
8459 let root = RenderRepaintBoundary::new(&mut app, Some(offstage.as_box()));
8460 let owner = first_frame(&mut app, root.as_box());
8461
8462 assert!(RenderObject::sized_by_parent(offstage, &app));
8463 assert_eq!(child.size(&app), Size::new(100.0, 100.0), "still laid out");
8464 assert!(
8465 !picture_has_clip(&app, root.as_object()),
8466 "offstage paints nothing"
8467 );
8468 assert_eq!(
8469 hit_test(&mut app, offstage.as_box(), Offset::new(50.0, 50.0)),
8470 (false, 0)
8471 );
8472 assert!(!offstage.paints_child(&app, child.as_box()));
8473
8474 offstage.set_offstage(&mut app, false);
8475 pump_frame(&mut app, owner);
8476 assert_eq!(
8477 drawn_rects(&app, root.as_object()),
8478 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8479 );
8480 assert!(hit_test(&mut app, offstage.as_box(), Offset::new(50.0, 50.0)).0);
8481 assert!(offstage.paints_child(&app, child.as_box()));
8482 }
8483
8484 #[test]
8485 fn colored_box_fills_its_bounds() {
8486 let cell = AppCell::new();
8487 let mut app = cell.borrow_mut();
8488 let colored = red_box(&mut app);
8489 let root = RenderRepaintBoundary::new(&mut app, Some(colored.as_box()));
8490 first_frame(&mut app, root.as_box());
8491
8492 assert_eq!(
8493 drawn_rects(&app, root.as_object()),
8494 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8495 );
8496 assert_eq!(
8497 hit_test(&mut app, colored.as_box(), Offset::new(50.0, 50.0)),
8498 (true, 1),
8499 "an opaque box is hit by itself"
8500 );
8501 }
8502
8503 #[test]
8504 fn colored_box_paints_its_child_over_the_color() {
8505 let cell = AppCell::new();
8506 let mut app = cell.borrow_mut();
8507 let child = red_box(&mut app);
8508 let colored = RenderColoredBox::new(&mut app, BLUE, true, Some(child.as_box()));
8509 let root = RenderRepaintBoundary::new(&mut app, Some(colored.as_box()));
8510 first_frame(&mut app, root.as_box());
8511
8512 let bounds = Rect::from_ltwh(0.0, 0.0, 100.0, 100.0);
8513 assert_eq!(
8514 drawn_rects(&app, root.as_object()),
8515 [fill(bounds, BLUE), fill(bounds, RED)]
8516 );
8517 }
8518
8519 #[test]
8520 fn meta_data_carries_its_payload_and_hit_tests_by_behavior() {
8521 let cell = AppCell::new();
8522 let mut app = cell.borrow_mut();
8523 let payload: Rc<dyn Any> = Rc::new(42u32);
8524 let opaque = RenderMetaData::new(
8525 &mut app,
8526 Some(Rc::clone(&payload)),
8527 HitTestBehavior::Opaque,
8528 None,
8529 );
8530 opaque.layout(
8531 &mut app,
8532 BoxConstraints::tight(Size::new(10.0, 10.0)),
8533 false,
8534 );
8535 assert_eq!(
8536 opaque
8537 .meta_data(&app)
8538 .and_then(|data| data.downcast::<u32>().ok())
8539 .as_deref(),
8540 Some(&42)
8541 );
8542 let mut result = HitTestResult::new();
8543 assert!(opaque.as_box().hit_test(
8544 &mut app,
8545 &mut BoxHitTestResult::wrap(&mut result),
8546 Offset::new(5.0, 5.0)
8547 ));
8548 assert_eq!(result.path().len(), 1);
8549
8550 let deferring = RenderMetaData::new(&mut app, None, HitTestBehavior::DeferToChild, None);
8551 deferring.layout(
8552 &mut app,
8553 BoxConstraints::tight(Size::new(10.0, 10.0)),
8554 false,
8555 );
8556 let mut result = HitTestResult::new();
8557 assert!(!deferring.as_box().hit_test(
8558 &mut app,
8559 &mut BoxHitTestResult::wrap(&mut result),
8560 Offset::new(5.0, 5.0)
8561 ));
8562 assert!(result.path().is_empty());
8563
8564 let child = opaque_leaf(&mut app);
8566 deferring.set_child(&mut app, Some(child.as_box()));
8567 deferring.layout(
8568 &mut app,
8569 BoxConstraints::tight(Size::new(10.0, 10.0)),
8570 false,
8571 );
8572 let mut result = HitTestResult::new();
8573 assert!(deferring.as_box().hit_test(
8574 &mut app,
8575 &mut BoxHitTestResult::wrap(&mut result),
8576 Offset::new(5.0, 5.0)
8577 ));
8578 assert_eq!(result.path().len(), 2, "the child, then the meta data");
8579 }
8580
8581 fn scene_ops(app: &mut App, root: AnyRenderObject) -> Vec<Op> {
8583 let scene = root
8584 .debug_layer(app)
8585 .expect("painted")
8586 .build_scene(app, SceneBuilder::new());
8587 inset_embedder::flattened_ops(&scene.picture)
8588 }
8589
8590 #[test]
8591 fn a_backdrop_filter_blurs_under_its_bounds_before_its_child_paints() {
8592 let cell = AppCell::new();
8593 let mut app = cell.borrow_mut();
8594 let child = RenderColoredBox::new(&mut app, Color::new(0xFF00FF00), true, None);
8595 let filter = RenderBackdropFilter::new(
8596 &mut app,
8597 ImageFilterConfig::new(ImageFilter::blur(6.0, 6.0)),
8598 BlendMode::SrcOver,
8599 true,
8600 None,
8601 Some(child.as_box()),
8602 );
8603 let root = RenderRepaintBoundary::new(&mut app, Some(filter.as_box()));
8604 let owner = first_frame(&mut app, root.as_box());
8605 let ops = scene_ops(&mut app, root.as_object());
8606 let blur = ops
8607 .iter()
8608 .position(|op| {
8609 matches!(
8610 op,
8611 Op::SaveLayer {
8612 backdrop: Some(_),
8613 ..
8614 }
8615 )
8616 })
8617 .expect("a backdrop layer");
8618 let draw = ops
8619 .iter()
8620 .position(|op| matches!(op, Op::DrawRect { .. }))
8621 .expect("the child's paint");
8622 assert!(blur < draw, "the blur precedes the child: {ops:?}");
8623 if let Op::SaveLayer {
8624 backdrop: Some(backdrop),
8625 ..
8626 } = &ops[blur]
8627 {
8628 assert_eq!(
8629 backdrop.filter,
8630 inset_embedder::valo::ImageFilter::blur(6.0, 6.0)
8631 );
8632 assert_eq!(backdrop.shared_key, None);
8633 }
8634
8635 let key = BackdropKey::new();
8636 filter.set_backdrop_key(&mut app, Some(key));
8637 pump_frame(&mut app, owner);
8638 let ops = scene_ops(&mut app, root.as_object());
8639 assert!(
8640 ops.iter().any(|op| matches!(
8641 op,
8642 Op::SaveLayer {
8643 backdrop: Some(valo::Backdrop {
8644 shared_key: Some(_),
8645 ..
8646 }),
8647 ..
8648 }
8649 )),
8650 "a keyed filter shares its blur: {ops:?}"
8651 );
8652
8653 filter.set_enabled(&mut app, false);
8654 pump_frame(&mut app, owner);
8655 let ops = scene_ops(&mut app, root.as_object());
8656 assert!(
8657 !ops.iter().any(|op| matches!(
8658 op,
8659 Op::SaveLayer {
8660 backdrop: Some(_),
8661 ..
8662 }
8663 )),
8664 "disabled paints the child only: {ops:?}"
8665 );
8666 }
8667
8668 #[test]
8669 fn a_composed_backdrop_filter_reaches_the_backdrop_whole() {
8670 let cell = AppCell::new();
8671 let mut app = cell.borrow_mut();
8672 let child = RenderColoredBox::new(&mut app, Color::new(0xFF00FF00), true, None);
8673 let saturation = ColorFilter::saturation(1.8);
8674 let filter = RenderBackdropFilter::new(
8675 &mut app,
8676 ImageFilterConfig::compose(
8677 ImageFilterConfig::new(ImageFilter::Color(saturation)),
8678 ImageFilterConfig::blur().sigma_x(4.0),
8679 ),
8680 BlendMode::SrcOver,
8681 true,
8682 None,
8683 Some(child.as_box()),
8684 );
8685 let root = RenderRepaintBoundary::new(&mut app, Some(filter.as_box()));
8686 first_frame(&mut app, root.as_box());
8687 let ops = scene_ops(&mut app, root.as_object());
8688 let composed = valo::ImageFilter::compose(
8689 valo::ImageFilter::Color(saturation.to_valo()),
8690 valo::ImageFilter::blur(4.0, 0.0),
8691 );
8692 assert!(
8693 ops.iter().any(|op| matches!(
8694 op,
8695 Op::SaveLayer {
8696 backdrop: Some(backdrop),
8697 ..
8698 } if backdrop.filter == composed
8699 )),
8700 "the saturation and the blur reach the backdrop in their order: {ops:?}"
8701 );
8702 }
8703
8704 #[test]
8705 fn clip_oval_hit_tests_inside_the_inscribed_oval_and_clips_with_its_path() {
8706 let cell = AppCell::new();
8707 let mut app = cell.borrow_mut();
8708 let child = opaque_leaf(&mut app);
8709 let oval = RenderClipOval::new(&mut app, None, Clip::AntiAlias, Some(child.as_box()));
8710 let root = RenderRepaintBoundary::new(&mut app, Some(oval.as_box()));
8711 first_frame(&mut app, root.as_box());
8712 let hit = |app: &mut App, x: f64, y: f64| {
8713 let mut result = HitTestResult::new();
8714 oval.as_box().hit_test(
8715 app,
8716 &mut BoxHitTestResult::wrap(&mut result),
8717 Offset::new(x, y),
8718 )
8719 };
8720 assert!(hit(&mut app, 50.0, 50.0), "the center is inside");
8721 assert!(!hit(&mut app, 2.0, 2.0), "a corner is outside the oval");
8722 assert!(
8723 picture_has_clip(&app, root.as_object()),
8724 "an oval clips with a path"
8725 );
8726 }
8727
8728 #[test]
8729 fn clip_path_uses_its_clipper_for_hit_tests_and_the_rect_by_default() {
8730 struct Triangle;
8731 impl CustomClipper<Arc<Path>> for Triangle {
8732 fn get_clip(&self, size: Size) -> Arc<Path> {
8733 let mut path = PathBuilder::new();
8734 path.move_to(Point::new(0.0, 0.0));
8735 path.line_to(Point::new(size.width() as f32, 0.0));
8736 path.line_to(Point::new(0.0, size.height() as f32));
8737 path.close();
8738 path.build()
8739 }
8740
8741 fn should_reclip(&self, _old: &dyn CustomClipper<Arc<Path>>) -> bool {
8742 false
8743 }
8744
8745 fn as_any(&self) -> &dyn Any {
8746 self
8747 }
8748 }
8749 let cell = AppCell::new();
8750 let mut app = cell.borrow_mut();
8751 let child = opaque_leaf(&mut app);
8752 let clip = RenderClipPath::new(
8753 &mut app,
8754 Some(Rc::new(Triangle)),
8755 Clip::AntiAlias,
8756 Some(child.as_box()),
8757 );
8758 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8759 first_frame(&mut app, root.as_box());
8760 let hit = |app: &mut App, x: f64, y: f64| {
8761 let mut result = HitTestResult::new();
8762 clip.as_box().hit_test(
8763 app,
8764 &mut BoxHitTestResult::wrap(&mut result),
8765 Offset::new(x, y),
8766 )
8767 };
8768 assert!(hit(&mut app, 10.0, 10.0), "inside the triangle");
8769 assert!(!hit(&mut app, 90.0, 90.0), "outside the triangle");
8770
8771 let plain = RenderClipPath::new(&mut app, None, Clip::HardEdge, None);
8772 plain.layout(
8773 &mut app,
8774 BoxConstraints::tight(Size::new(30.0, 20.0)),
8775 false,
8776 );
8777 assert!(
8778 plain
8779 .default_clip(&app)
8780 .contains(Point::new(29.0, 19.0), FillRule::NonZero),
8781 "the default clip is the box's rect"
8782 );
8783 }
8784
8785 #[test]
8786 fn clip_rsuperellipse_resolves_its_border_radius_and_clips_with_a_path() {
8787 let cell = AppCell::new();
8788 let mut app = cell.borrow_mut();
8789 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::expand(None, None), None);
8790 let clip = RenderClipRSuperellipse::new(
8791 &mut app,
8792 BorderRadiusGeometry::circular(12.0),
8793 None,
8794 Clip::AntiAlias,
8795 Some(TextDirection::Ltr),
8796 Some(child.as_box()),
8797 );
8798 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8799 first_frame(&mut app, root.as_box());
8800 clip.update_clip(&mut app);
8801 assert_eq!(clip.clip(&app).tl_radius_x, 12.0);
8802 assert_eq!(
8803 clip.clip(&app).outer_rect(),
8804 Rect::from_ltwh(0.0, 0.0, 100.0, 100.0)
8805 );
8806 assert!(
8807 picture_has_clip(&app, root.as_object()),
8808 "a superellipse clips with its path"
8809 );
8810 clip.set_border_radius(&mut app, BorderRadiusGeometry::circular(4.0));
8811 assert!(
8812 clip.custom_clip_data(&app).clip.is_none(),
8813 "a new radius marks the clip"
8814 );
8815 }
8816
8817 #[test]
8818 fn a_shape_border_clipper_clips_to_the_shape_and_reclips_when_it_changes() {
8819 let square: Box<dyn ShapeBorder> = Box::new(inset_painting::RoundedRectangleBorder::new(
8820 inset_painting::BorderSide::NONE,
8821 inset_painting::BorderRadiusGeometry::circular(10.0),
8822 ));
8823 let clipper = ShapeBorderClipper::new(square.clone_box(), Some(TextDirection::Ltr));
8824 let clip = clipper.get_clip(Size::new(40.0, 40.0));
8825 assert!(clip.contains(Point::new(20.0, 20.0), FillRule::NonZero));
8826 assert!(
8827 !clip.contains(Point::new(0.5, 0.5), FillRule::NonZero),
8828 "a rounded corner"
8829 );
8830 let same = ShapeBorderClipper::new(square.clone_box(), Some(TextDirection::Ltr));
8831 assert!(!clipper.should_reclip(&same));
8832 let other = ShapeBorderClipper::new(square, Some(TextDirection::Rtl));
8833 assert!(clipper.should_reclip(&other));
8834 }
8835}