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.painter.get_or_insert_with(|| {
1955 this.decoration
1956 .create_box_painter(Some(Rc::new(move |app| self.mark_needs_paint(app))))
1957 });
1958 painter.paint(context.canvas(), offset, configuration);
1959 this.decoration.is_complex()
1960 };
1961 debug_assert_eq!(
1962 debug_save_count,
1963 context.canvas().save_count(),
1964 "the decoration's painter had mismatching save and restore calls"
1965 );
1966 if is_complex {
1967 context.set_is_complex_hint();
1968 }
1969 }
1970}
1971
1972impl RenderObjectWithChildMixin for RenderDecoratedBox {
1973 type ChildType = AnyRenderBox;
1974
1975 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
1976 &self.get(app).child
1977 }
1978
1979 fn child_data_mut(
1980 self: RenderHandle<Self>,
1981 app: &mut App,
1982 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
1983 &mut self.get_mut(app).child
1984 }
1985}
1986
1987impl RenderProxyBoxMixin for RenderDecoratedBox {}
1988
1989impl RenderObject for RenderDecoratedBox {
1990 crate::render_object_accessors!();
1991
1992 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
1993 if let Some(mut painter) = self.get_mut(app).painter.take() {
1994 painter.dispose();
1995 }
1996 if let Some(child) = self.child(app) {
1997 child.as_object().detach(app);
1998 }
1999 self.mark_needs_paint(app);
2000 }
2001
2002 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2003 RenderProxyBoxMixin::perform_layout(self, app);
2004 }
2005
2006 fn paint(
2007 self: RenderHandle<Self>,
2008 app: &mut App,
2009 context: &mut PaintingContext,
2010 offset: Offset,
2011 ) {
2012 let size = self.size(app);
2013 let filled_configuration =
2014 self.get(app)
2015 .configuration
2016 .copy_with(None, None, None, None, Some(size), None);
2017 if self.get(app).position == DecorationPosition::Background {
2018 self.paint_decoration(app, context, offset, &filled_configuration);
2019 }
2020 RenderProxyBoxMixin::paint(self, app, context, offset);
2021 if self.get(app).position == DecorationPosition::Foreground {
2022 self.paint_decoration(app, context, offset, &filled_configuration);
2023 }
2024 }
2025
2026 fn visit_children(
2027 self: RenderHandle<Self>,
2028 app: &App,
2029 visitor: &mut dyn FnMut(AnyRenderObject),
2030 ) {
2031 if let Some(child) = self.child(app) {
2032 visitor(child.as_object());
2033 }
2034 }
2035}
2036
2037impl RenderBox for RenderDecoratedBox {
2038 crate::render_box_accessors!();
2039
2040 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
2041 let this = self.get(app);
2042 this.decoration
2043 .hit_test(self.size(app), position, this.configuration.text_direction)
2044 }
2045
2046 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2047 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2048 }
2049
2050 fn apply_paint_transform(
2051 self: RenderHandle<Self>,
2052 app: &App,
2053 child: AnyRenderObject,
2054 transform: &mut Matrix4,
2055 ) {
2056 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2057 }
2058
2059 fn hit_test_children(
2060 self: RenderHandle<Self>,
2061 app: &mut App,
2062 result: &mut BoxHitTestResult<'_>,
2063 position: Offset,
2064 ) -> bool {
2065 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2066 }
2067
2068 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2069 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2070 }
2071
2072 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2073 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2074 }
2075
2076 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2077 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2078 }
2079
2080 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2081 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2082 }
2083
2084 fn compute_distance_to_actual_baseline(
2085 self: RenderHandle<Self>,
2086 app: &mut App,
2087 baseline: TextBaseline,
2088 ) -> Option<f64> {
2089 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2090 }
2091
2092 fn compute_dry_baseline(
2093 self: RenderHandle<Self>,
2094 app: &mut App,
2095 constraints: BoxConstraints,
2096 baseline: TextBaseline,
2097 ) -> Option<f64> {
2098 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2099 }
2100
2101 fn compute_dry_layout(
2102 self: RenderHandle<Self>,
2103 app: &mut App,
2104 constraints: BoxConstraints,
2105 ) -> Size {
2106 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2107 }
2108}
2109
2110pub struct RenderRepaintBoundary {
2116 render_object: RenderObjectData,
2117 render_box: RenderBoxData,
2118 child: RenderObjectWithChildData<AnyRenderBox>,
2119}
2120
2121impl RenderRepaintBoundary {
2122 pub fn new(app: &mut App, child: Option<AnyRenderBox>) -> RenderHandle<Self> {
2124 let this = RenderHandle::new_box(
2125 app,
2126 RenderRepaintBoundary {
2127 render_object: RenderObjectData::new(),
2128 render_box: RenderBoxData::new(),
2129 child: RenderObjectWithChildData::new(),
2130 },
2131 );
2132 this.set_child(app, child);
2133 this
2134 }
2135}
2136
2137impl RenderObjectWithChildMixin for RenderRepaintBoundary {
2138 type ChildType = AnyRenderBox;
2139
2140 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2141 &self.get(app).child
2142 }
2143
2144 fn child_data_mut(
2145 self: RenderHandle<Self>,
2146 app: &mut App,
2147 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2148 &mut self.get_mut(app).child
2149 }
2150}
2151
2152impl RenderProxyBoxMixin for RenderRepaintBoundary {}
2153
2154impl RenderObject for RenderRepaintBoundary {
2155 crate::render_object_accessors!();
2156
2157 fn is_repaint_boundary(self: RenderHandle<Self>, _app: &App) -> bool {
2158 true
2159 }
2160
2161 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2162 RenderProxyBoxMixin::perform_layout(self, app);
2163 }
2164
2165 fn paint(
2166 self: RenderHandle<Self>,
2167 app: &mut App,
2168 context: &mut PaintingContext,
2169 offset: Offset,
2170 ) {
2171 RenderProxyBoxMixin::paint(self, app, context, offset);
2172 }
2173
2174 fn visit_children(
2175 self: RenderHandle<Self>,
2176 app: &App,
2177 visitor: &mut dyn FnMut(AnyRenderObject),
2178 ) {
2179 if let Some(child) = self.child(app) {
2180 visitor(child.as_object());
2181 }
2182 }
2183}
2184
2185impl RenderBox for RenderRepaintBoundary {
2186 crate::render_box_accessors!();
2187
2188 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2189 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2190 }
2191
2192 fn apply_paint_transform(
2193 self: RenderHandle<Self>,
2194 app: &App,
2195 child: AnyRenderObject,
2196 transform: &mut Matrix4,
2197 ) {
2198 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2199 }
2200
2201 fn hit_test_children(
2202 self: RenderHandle<Self>,
2203 app: &mut App,
2204 result: &mut BoxHitTestResult<'_>,
2205 position: Offset,
2206 ) -> bool {
2207 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2208 }
2209
2210 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2211 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2212 }
2213
2214 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2215 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2216 }
2217
2218 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2219 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2220 }
2221
2222 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2223 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2224 }
2225
2226 fn compute_distance_to_actual_baseline(
2227 self: RenderHandle<Self>,
2228 app: &mut App,
2229 baseline: TextBaseline,
2230 ) -> Option<f64> {
2231 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2232 }
2233
2234 fn compute_dry_baseline(
2235 self: RenderHandle<Self>,
2236 app: &mut App,
2237 constraints: BoxConstraints,
2238 baseline: TextBaseline,
2239 ) -> Option<f64> {
2240 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2241 }
2242
2243 fn compute_dry_layout(
2244 self: RenderHandle<Self>,
2245 app: &mut App,
2246 constraints: BoxConstraints,
2247 ) -> Size {
2248 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2249 }
2250}
2251
2252pub struct RenderMouseRegion {
2274 render_object: RenderObjectData,
2275 render_box: RenderBoxData,
2276 child: RenderObjectWithChildData<AnyRenderBox>,
2277 on_enter: Option<PointerEnterEventListener>,
2278 on_hover: Option<PointerHoverEventListener>,
2279 on_exit: Option<PointerExitEventListener>,
2280 cursor: MouseCursorRef,
2281 valid_for_mouse_tracker: bool,
2282 opaque: bool,
2283 behavior: HitTestBehavior,
2284}
2285
2286impl RenderMouseRegion {
2287 pub fn new(
2293 app: &mut App,
2294 valid_for_mouse_tracker: bool,
2295 child: Option<AnyRenderBox>,
2296 ) -> RenderHandle<Self> {
2297 let this = RenderHandle::new_box(
2298 app,
2299 RenderMouseRegion {
2300 render_object: RenderObjectData::new(),
2301 render_box: RenderBoxData::new(),
2302 child: RenderObjectWithChildData::new(),
2303 on_enter: None,
2304 on_hover: None,
2305 on_exit: None,
2306 cursor: <dyn MouseCursor>::defer(),
2307 valid_for_mouse_tracker,
2308 opaque: true,
2309 behavior: HitTestBehavior::Opaque,
2310 },
2311 );
2312 this.set_child(app, child);
2313 this
2314 }
2315
2316 pub fn opaque(self: RenderHandle<Self>, app: &App) -> bool {
2331 self.get(app).opaque
2332 }
2333
2334 pub fn set_opaque(self: RenderHandle<Self>, app: &mut App, value: bool) {
2336 if self.get(app).opaque != value {
2337 self.get_mut(app).opaque = value;
2338 self.mark_needs_paint(app);
2340 }
2341 }
2342
2343 pub fn hit_test_behavior(self: RenderHandle<Self>, app: &App) -> Option<HitTestBehavior> {
2347 Some(self.get(app).behavior)
2348 }
2349
2350 pub fn set_hit_test_behavior(
2352 self: RenderHandle<Self>,
2353 app: &mut App,
2354 value: Option<HitTestBehavior>,
2355 ) {
2356 let new_value = value.unwrap_or(HitTestBehavior::Opaque);
2357 if self.get(app).behavior != new_value {
2358 self.get_mut(app).behavior = new_value;
2359 self.mark_needs_paint(app);
2361 }
2362 }
2363
2364 pointer_listener_field!(
2365 on_enter,
2366 set_on_enter,
2367 PointerEnterEventListener,
2368 "Triggered when a mouse pointer, with or without buttons pressed, has entered the region and `valid_for_mouse_tracker` is true."
2369 );
2370 pointer_listener_field!(
2371 on_hover,
2372 set_on_hover,
2373 PointerHoverEventListener,
2374 "Triggered when a pointer has moved onto or within the region without buttons pressed."
2375 );
2376 pointer_listener_field!(
2377 on_exit,
2378 set_on_exit,
2379 PointerExitEventListener,
2380 "Triggered when a mouse pointer, with or without buttons pressed, has exited the region and `valid_for_mouse_tracker` is true."
2381 );
2382
2383 pub fn cursor(self: RenderHandle<Self>, app: &App) -> MouseCursorRef {
2392 Rc::clone(&self.get(app).cursor)
2393 }
2394
2395 pub fn set_cursor(self: RenderHandle<Self>, app: &mut App, value: MouseCursorRef) {
2397 if *self.get(app).cursor != *value {
2398 self.get_mut(app).cursor = value;
2399 self.mark_needs_paint(app);
2402 }
2403 }
2404
2405 pub fn valid_for_mouse_tracker(self: RenderHandle<Self>, app: &App) -> bool {
2408 self.get(app).valid_for_mouse_tracker
2409 }
2410}
2411
2412impl RenderObjectWithChildMixin for RenderMouseRegion {
2413 type ChildType = AnyRenderBox;
2414
2415 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2416 &self.get(app).child
2417 }
2418
2419 fn child_data_mut(
2420 self: RenderHandle<Self>,
2421 app: &mut App,
2422 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2423 &mut self.get_mut(app).child
2424 }
2425}
2426
2427impl RenderProxyBoxMixin for RenderMouseRegion {
2428 fn compute_size_for_no_child(
2429 self: RenderHandle<Self>,
2430 _app: &App,
2431 constraints: BoxConstraints,
2432 ) -> Size {
2433 constraints.biggest()
2434 }
2435}
2436
2437impl RenderProxyBoxWithHitTestBehavior for RenderMouseRegion {
2438 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
2439 self.get(app).behavior
2440 }
2441}
2442
2443impl RenderObject for RenderMouseRegion {
2444 crate::render_object_accessors!();
2445
2446 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
2447 for child in [self.child(app)].into_iter().flatten() {
2448 child.as_object().attach(app, owner);
2449 }
2450 self.get_mut(app).valid_for_mouse_tracker = true;
2451 }
2452
2453 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
2454 self.get_mut(app).valid_for_mouse_tracker = false;
2456 for child in [self.child(app)].into_iter().flatten() {
2457 child.as_object().detach(app);
2458 }
2459 }
2460
2461 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2462 RenderProxyBoxMixin::perform_layout(self, app);
2463 }
2464
2465 fn mouse_tracker_annotation(
2466 self: RenderHandle<Self>,
2467 app: &App,
2468 ) -> Option<MouseTrackerAnnotation> {
2469 let this = self.get(app);
2470 Some(MouseTrackerAnnotation {
2471 on_enter: this.on_enter.clone(),
2472 on_exit: this.on_exit.clone(),
2473 cursor: Rc::clone(&this.cursor),
2474 valid_for_mouse_tracker: this.valid_for_mouse_tracker,
2475 })
2476 }
2477
2478 fn paint(
2479 self: RenderHandle<Self>,
2480 app: &mut App,
2481 context: &mut PaintingContext,
2482 offset: Offset,
2483 ) {
2484 RenderProxyBoxMixin::paint(self, app, context, offset);
2485 }
2486
2487 fn visit_children(
2488 self: RenderHandle<Self>,
2489 app: &App,
2490 visitor: &mut dyn FnMut(AnyRenderObject),
2491 ) {
2492 if let Some(child) = self.child(app) {
2493 visitor(child.as_object());
2494 }
2495 }
2496}
2497
2498impl RenderBox for RenderMouseRegion {
2499 crate::render_box_accessors!();
2500
2501 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2502 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2503 }
2504
2505 fn apply_paint_transform(
2506 self: RenderHandle<Self>,
2507 app: &App,
2508 child: AnyRenderObject,
2509 transform: &mut Matrix4,
2510 ) {
2511 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2512 }
2513
2514 fn hit_test(
2515 self: RenderHandle<Self>,
2516 app: &mut App,
2517 result: &mut BoxHitTestResult<'_>,
2518 position: Offset,
2519 ) -> bool {
2520 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
2521 && self.get(app).opaque
2522 }
2523
2524 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
2525 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
2526 }
2527
2528 fn hit_test_children(
2529 self: RenderHandle<Self>,
2530 app: &mut App,
2531 result: &mut BoxHitTestResult<'_>,
2532 position: Offset,
2533 ) -> bool {
2534 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2535 }
2536
2537 fn handle_event(
2538 self: RenderHandle<Self>,
2539 app: &mut App,
2540 event: &PointerEvent,
2541 _entry: &BoxHitTestEntry,
2542 ) {
2543 if let PointerEvent::Hover(event) = event
2544 && let Some(on_hover) = self.get(app).on_hover.clone()
2545 {
2546 on_hover(app, event.clone());
2547 }
2548 }
2549
2550 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2551 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2552 }
2553
2554 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2555 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2556 }
2557
2558 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2559 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2560 }
2561
2562 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2563 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2564 }
2565
2566 fn compute_distance_to_actual_baseline(
2567 self: RenderHandle<Self>,
2568 app: &mut App,
2569 baseline: TextBaseline,
2570 ) -> Option<f64> {
2571 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2572 }
2573
2574 fn compute_dry_baseline(
2575 self: RenderHandle<Self>,
2576 app: &mut App,
2577 constraints: BoxConstraints,
2578 baseline: TextBaseline,
2579 ) -> Option<f64> {
2580 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2581 }
2582
2583 fn compute_dry_layout(
2584 self: RenderHandle<Self>,
2585 app: &mut App,
2586 constraints: BoxConstraints,
2587 ) -> Size {
2588 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
2589 }
2590}
2591
2592pub(crate) fn same_instance<T: ?Sized>(a: Option<&Rc<T>>, b: Option<&Rc<T>>) -> bool {
2594 match (a, b) {
2595 (None, None) => true,
2596 (Some(a), Some(b)) => Rc::ptr_eq(a, b),
2597 _ => false,
2598 }
2599}
2600
2601pub struct RenderLimitedBox {
2614 render_object: RenderObjectData,
2615 render_box: RenderBoxData,
2616 child: RenderObjectWithChildData<AnyRenderBox>,
2617 max_width: f64,
2618 max_height: f64,
2619}
2620
2621impl RenderLimitedBox {
2622 pub fn new(
2627 app: &mut App,
2628 max_width: f64,
2629 max_height: f64,
2630 child: Option<AnyRenderBox>,
2631 ) -> RenderHandle<RenderLimitedBox> {
2632 debug_assert!(max_width >= 0.0);
2633 debug_assert!(max_height >= 0.0);
2634 let this = RenderHandle::new_box(
2635 app,
2636 RenderLimitedBox {
2637 render_object: RenderObjectData::new(),
2638 render_box: RenderBoxData::new(),
2639 child: RenderObjectWithChildData::new(),
2640 max_width,
2641 max_height,
2642 },
2643 );
2644 this.set_child(app, child);
2645 this
2646 }
2647
2648 pub fn max_width(self: RenderHandle<Self>, app: &App) -> f64 {
2650 self.get(app).max_width
2651 }
2652
2653 pub fn set_max_width(self: RenderHandle<Self>, app: &mut App, value: f64) {
2655 debug_assert!(value >= 0.0);
2656 if self.get(app).max_width == value {
2657 return;
2658 }
2659 self.get_mut(app).max_width = value;
2660 self.mark_needs_layout(app);
2661 }
2662
2663 pub fn max_height(self: RenderHandle<Self>, app: &App) -> f64 {
2665 self.get(app).max_height
2666 }
2667
2668 pub fn set_max_height(self: RenderHandle<Self>, app: &mut App, value: f64) {
2670 debug_assert!(value >= 0.0);
2671 if self.get(app).max_height == value {
2672 return;
2673 }
2674 self.get_mut(app).max_height = value;
2675 self.mark_needs_layout(app);
2676 }
2677
2678 fn compute_size(
2680 self: RenderHandle<Self>,
2681 app: &mut App,
2682 constraints: BoxConstraints,
2683 layout_child: ChildLayouter,
2684 ) -> Size {
2685 let limited = self.limit_constraints(app, constraints);
2686 match self.child(app) {
2687 Some(child) => constraints.constrain(layout_child(app, child, limited)),
2688 None => limited.constrain(Size::ZERO),
2689 }
2690 }
2691
2692 fn limit_constraints(
2693 self: RenderHandle<Self>,
2694 app: &App,
2695 constraints: BoxConstraints,
2696 ) -> BoxConstraints {
2697 let this = self.get(app);
2698 BoxConstraints::new()
2699 .min_width(constraints.min_width)
2700 .max_width(if constraints.has_bounded_width() {
2701 constraints.max_width
2702 } else {
2703 constraints.constrain_width(this.max_width)
2704 })
2705 .min_height(constraints.min_height)
2706 .max_height(if constraints.has_bounded_height() {
2707 constraints.max_height
2708 } else {
2709 constraints.constrain_height(this.max_height)
2710 })
2711 }
2712}
2713
2714impl RenderObjectWithChildMixin for RenderLimitedBox {
2715 type ChildType = AnyRenderBox;
2716
2717 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2718 &self.get(app).child
2719 }
2720
2721 fn child_data_mut(
2722 self: RenderHandle<Self>,
2723 app: &mut App,
2724 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2725 &mut self.get_mut(app).child
2726 }
2727}
2728
2729impl RenderProxyBoxMixin for RenderLimitedBox {}
2730
2731impl RenderObject for RenderLimitedBox {
2732 crate::render_object_accessors!();
2733
2734 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2735 let constraints = self.constraints(app);
2736 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
2737 self.set_size(app, size);
2738 }
2739
2740 fn paint(
2741 self: RenderHandle<Self>,
2742 app: &mut App,
2743 context: &mut PaintingContext,
2744 offset: Offset,
2745 ) {
2746 RenderProxyBoxMixin::paint(self, app, context, offset);
2747 }
2748
2749 fn visit_children(
2750 self: RenderHandle<Self>,
2751 app: &App,
2752 visitor: &mut dyn FnMut(AnyRenderObject),
2753 ) {
2754 if let Some(child) = self.child(app) {
2755 visitor(child.as_object());
2756 }
2757 }
2758}
2759
2760impl RenderBox for RenderLimitedBox {
2761 crate::render_box_accessors!();
2762
2763 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
2764 RenderProxyBoxMixin::setup_parent_data(self, app, child);
2765 }
2766
2767 fn apply_paint_transform(
2768 self: RenderHandle<Self>,
2769 app: &App,
2770 child: AnyRenderObject,
2771 transform: &mut Matrix4,
2772 ) {
2773 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
2774 }
2775
2776 fn hit_test_children(
2777 self: RenderHandle<Self>,
2778 app: &mut App,
2779 result: &mut BoxHitTestResult<'_>,
2780 position: Offset,
2781 ) -> bool {
2782 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
2783 }
2784
2785 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2786 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
2787 }
2788
2789 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
2790 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
2791 }
2792
2793 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2794 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
2795 }
2796
2797 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
2798 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
2799 }
2800
2801 fn compute_distance_to_actual_baseline(
2802 self: RenderHandle<Self>,
2803 app: &mut App,
2804 baseline: TextBaseline,
2805 ) -> Option<f64> {
2806 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
2807 }
2808
2809 fn compute_dry_baseline(
2810 self: RenderHandle<Self>,
2811 app: &mut App,
2812 constraints: BoxConstraints,
2813 baseline: TextBaseline,
2814 ) -> Option<f64> {
2815 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
2816 }
2817
2818 fn compute_dry_layout(
2819 self: RenderHandle<Self>,
2820 app: &mut App,
2821 constraints: BoxConstraints,
2822 ) -> Size {
2823 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
2824 }
2825}
2826
2827pub struct RenderAspectRatio {
2841 render_object: RenderObjectData,
2842 render_box: RenderBoxData,
2843 child: RenderObjectWithChildData<AnyRenderBox>,
2844 aspect_ratio: f64,
2845}
2846
2847impl RenderAspectRatio {
2848 pub fn new(
2852 app: &mut App,
2853 aspect_ratio: f64,
2854 child: Option<AnyRenderBox>,
2855 ) -> RenderHandle<RenderAspectRatio> {
2856 debug_assert!(aspect_ratio > 0.0);
2857 debug_assert!(aspect_ratio.is_finite());
2858 let this = RenderHandle::new_box(
2859 app,
2860 RenderAspectRatio {
2861 render_object: RenderObjectData::new(),
2862 render_box: RenderBoxData::new(),
2863 child: RenderObjectWithChildData::new(),
2864 aspect_ratio,
2865 },
2866 );
2867 this.set_child(app, child);
2868 this
2869 }
2870
2871 pub fn aspect_ratio(self: RenderHandle<Self>, app: &App) -> f64 {
2876 self.get(app).aspect_ratio
2877 }
2878
2879 pub fn set_aspect_ratio(self: RenderHandle<Self>, app: &mut App, value: f64) {
2881 debug_assert!(value > 0.0);
2882 debug_assert!(value.is_finite());
2883 if self.get(app).aspect_ratio == value {
2884 return;
2885 }
2886 self.get_mut(app).aspect_ratio = value;
2887 self.mark_needs_layout(app);
2888 }
2889
2890 fn apply_aspect_ratio(
2891 self: RenderHandle<Self>,
2892 app: &App,
2893 constraints: BoxConstraints,
2894 ) -> Size {
2895 debug_assert!(constraints.debug_assert_is_valid(false));
2896 let aspect_ratio = self.get(app).aspect_ratio;
2897 debug_assert!(
2898 constraints.has_bounded_width() || constraints.has_bounded_height(),
2899 "{} has unbounded constraints.\n\
2900 This render object was given an aspect ratio of {aspect_ratio} but was given both \
2901 unbounded width and unbounded height constraints. Because both constraints were \
2902 unbounded, this render object doesn't know how much size to consume.",
2903 std::any::type_name::<Self>()
2904 );
2905
2906 if constraints.is_tight() {
2907 return constraints.smallest();
2908 }
2909
2910 let mut width = constraints.max_width;
2911 let mut height;
2912
2913 if width.is_finite() {
2916 height = width / aspect_ratio;
2917 } else {
2918 height = constraints.max_height;
2919 width = height * aspect_ratio;
2920 }
2921
2922 if width > constraints.max_width {
2927 width = constraints.max_width;
2928 height = width / aspect_ratio;
2929 }
2930
2931 if height > constraints.max_height {
2932 height = constraints.max_height;
2933 width = height * aspect_ratio;
2934 }
2935
2936 if width < constraints.min_width {
2937 width = constraints.min_width;
2938 height = width / aspect_ratio;
2939 }
2940
2941 if height < constraints.min_height {
2942 height = constraints.min_height;
2943 width = height * aspect_ratio;
2944 }
2945
2946 constraints.constrain(Size::new(width, height))
2947 }
2948}
2949
2950impl RenderObjectWithChildMixin for RenderAspectRatio {
2951 type ChildType = AnyRenderBox;
2952
2953 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
2954 &self.get(app).child
2955 }
2956
2957 fn child_data_mut(
2958 self: RenderHandle<Self>,
2959 app: &mut App,
2960 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
2961 &mut self.get_mut(app).child
2962 }
2963}
2964
2965impl RenderProxyBoxMixin for RenderAspectRatio {}
2966
2967impl RenderObject for RenderAspectRatio {
2968 crate::render_object_accessors!();
2969
2970 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2971 let constraints = self.constraints(app);
2972 let size = self.get_dry_layout(app, constraints);
2973 self.set_size(app, size);
2974 if let Some(child) = self.child(app) {
2975 child.layout(app, BoxConstraints::tight(size), false);
2976 }
2977 }
2978
2979 fn paint(
2980 self: RenderHandle<Self>,
2981 app: &mut App,
2982 context: &mut PaintingContext,
2983 offset: Offset,
2984 ) {
2985 RenderProxyBoxMixin::paint(self, app, context, offset);
2986 }
2987
2988 fn visit_children(
2989 self: RenderHandle<Self>,
2990 app: &App,
2991 visitor: &mut dyn FnMut(AnyRenderObject),
2992 ) {
2993 if let Some(child) = self.child(app) {
2994 visitor(child.as_object());
2995 }
2996 }
2997}
2998
2999impl RenderBox for RenderAspectRatio {
3000 crate::render_box_accessors!();
3001
3002 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3003 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3004 }
3005
3006 fn apply_paint_transform(
3007 self: RenderHandle<Self>,
3008 app: &App,
3009 child: AnyRenderObject,
3010 transform: &mut Matrix4,
3011 ) {
3012 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3013 }
3014
3015 fn hit_test_children(
3016 self: RenderHandle<Self>,
3017 app: &mut App,
3018 result: &mut BoxHitTestResult<'_>,
3019 position: Offset,
3020 ) -> bool {
3021 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3022 }
3023
3024 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3025 if height.is_finite() {
3026 return height * self.get(app).aspect_ratio;
3027 }
3028 match self.child(app) {
3029 Some(child) => child.get_min_intrinsic_width(app, height),
3030 None => 0.0,
3031 }
3032 }
3033
3034 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3035 if height.is_finite() {
3036 return height * self.get(app).aspect_ratio;
3037 }
3038 match self.child(app) {
3039 Some(child) => child.get_max_intrinsic_width(app, height),
3040 None => 0.0,
3041 }
3042 }
3043
3044 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3045 if width.is_finite() {
3046 return width / self.get(app).aspect_ratio;
3047 }
3048 match self.child(app) {
3049 Some(child) => child.get_min_intrinsic_height(app, width),
3050 None => 0.0,
3051 }
3052 }
3053
3054 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3055 if width.is_finite() {
3056 return width / self.get(app).aspect_ratio;
3057 }
3058 match self.child(app) {
3059 Some(child) => child.get_max_intrinsic_height(app, width),
3060 None => 0.0,
3061 }
3062 }
3063
3064 fn compute_distance_to_actual_baseline(
3065 self: RenderHandle<Self>,
3066 app: &mut App,
3067 baseline: TextBaseline,
3068 ) -> Option<f64> {
3069 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3070 }
3071
3072 fn compute_dry_layout(
3073 self: RenderHandle<Self>,
3074 app: &mut App,
3075 constraints: BoxConstraints,
3076 ) -> Size {
3077 self.apply_aspect_ratio(app, constraints)
3078 }
3079
3080 fn compute_dry_baseline(
3081 self: RenderHandle<Self>,
3082 app: &mut App,
3083 constraints: BoxConstraints,
3084 baseline: TextBaseline,
3085 ) -> Option<f64> {
3086 let size = self.get_dry_layout(app, constraints);
3087 RenderProxyBoxMixin::compute_dry_baseline(self, app, BoxConstraints::tight(size), baseline)
3088 }
3089}
3090
3091pub struct RenderIntrinsicWidth {
3111 render_object: RenderObjectData,
3112 render_box: RenderBoxData,
3113 child: RenderObjectWithChildData<AnyRenderBox>,
3114 step_width: Option<f64>,
3115 step_height: Option<f64>,
3116}
3117
3118fn apply_step(input: f64, step: Option<f64>) -> f64 {
3120 debug_assert!(input.is_finite());
3121 match step {
3122 Some(step) => (input / step).ceil() * step,
3123 None => input,
3124 }
3125}
3126
3127impl RenderIntrinsicWidth {
3128 pub fn new(
3133 app: &mut App,
3134 step_width: Option<f64>,
3135 step_height: Option<f64>,
3136 child: Option<AnyRenderBox>,
3137 ) -> RenderHandle<RenderIntrinsicWidth> {
3138 debug_assert!(step_width.is_none_or(|step| step > 0.0));
3139 debug_assert!(step_height.is_none_or(|step| step > 0.0));
3140 let this = RenderHandle::new_box(
3141 app,
3142 RenderIntrinsicWidth {
3143 render_object: RenderObjectData::new(),
3144 render_box: RenderBoxData::new(),
3145 child: RenderObjectWithChildData::new(),
3146 step_width,
3147 step_height,
3148 },
3149 );
3150 this.set_child(app, child);
3151 this
3152 }
3153
3154 pub fn step_width(self: RenderHandle<Self>, app: &App) -> Option<f64> {
3156 self.get(app).step_width
3157 }
3158
3159 pub fn set_step_width(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
3161 debug_assert!(value.is_none_or(|step| step > 0.0));
3162 if self.get(app).step_width == value {
3163 return;
3164 }
3165 self.get_mut(app).step_width = value;
3166 self.mark_needs_layout(app);
3167 }
3168
3169 pub fn step_height(self: RenderHandle<Self>, app: &App) -> Option<f64> {
3171 self.get(app).step_height
3172 }
3173
3174 pub fn set_step_height(self: RenderHandle<Self>, app: &mut App, value: Option<f64>) {
3176 debug_assert!(value.is_none_or(|step| step > 0.0));
3177 if self.get(app).step_height == value {
3178 return;
3179 }
3180 self.get_mut(app).step_height = value;
3181 self.mark_needs_layout(app);
3182 }
3183
3184 fn child_constraints(
3185 self: RenderHandle<Self>,
3186 app: &mut App,
3187 child: AnyRenderBox,
3188 constraints: BoxConstraints,
3189 ) -> BoxConstraints {
3190 let (step_width, step_height) = {
3191 let this = self.get(app);
3192 (this.step_width, this.step_height)
3193 };
3194 let width = if constraints.has_tight_width() {
3195 None
3196 } else {
3197 Some(apply_step(
3198 child.get_max_intrinsic_width(app, constraints.max_height),
3199 step_width,
3200 ))
3201 };
3202 let height = step_height.map(|_| {
3203 apply_step(
3204 child.get_max_intrinsic_height(app, constraints.max_width),
3205 step_height,
3206 )
3207 });
3208 constraints.tighten(width, height)
3209 }
3210
3211 fn compute_size(
3213 self: RenderHandle<Self>,
3214 app: &mut App,
3215 constraints: BoxConstraints,
3216 layout_child: ChildLayouter,
3217 ) -> Size {
3218 match self.child(app) {
3219 Some(child) => {
3220 let child_constraints = self.child_constraints(app, child, constraints);
3221 layout_child(app, child, child_constraints)
3222 }
3223 None => constraints.smallest(),
3224 }
3225 }
3226}
3227
3228impl RenderObjectWithChildMixin for RenderIntrinsicWidth {
3229 type ChildType = AnyRenderBox;
3230
3231 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3232 &self.get(app).child
3233 }
3234
3235 fn child_data_mut(
3236 self: RenderHandle<Self>,
3237 app: &mut App,
3238 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3239 &mut self.get_mut(app).child
3240 }
3241}
3242
3243impl RenderProxyBoxMixin for RenderIntrinsicWidth {}
3244
3245impl RenderObject for RenderIntrinsicWidth {
3246 crate::render_object_accessors!();
3247
3248 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3249 let constraints = self.constraints(app);
3250 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
3251 self.set_size(app, size);
3252 }
3253
3254 fn paint(
3255 self: RenderHandle<Self>,
3256 app: &mut App,
3257 context: &mut PaintingContext,
3258 offset: Offset,
3259 ) {
3260 RenderProxyBoxMixin::paint(self, app, context, offset);
3261 }
3262
3263 fn visit_children(
3264 self: RenderHandle<Self>,
3265 app: &App,
3266 visitor: &mut dyn FnMut(AnyRenderObject),
3267 ) {
3268 if let Some(child) = self.child(app) {
3269 visitor(child.as_object());
3270 }
3271 }
3272}
3273
3274impl RenderBox for RenderIntrinsicWidth {
3275 crate::render_box_accessors!();
3276
3277 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3278 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3279 }
3280
3281 fn apply_paint_transform(
3282 self: RenderHandle<Self>,
3283 app: &App,
3284 child: AnyRenderObject,
3285 transform: &mut Matrix4,
3286 ) {
3287 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3288 }
3289
3290 fn hit_test_children(
3291 self: RenderHandle<Self>,
3292 app: &mut App,
3293 result: &mut BoxHitTestResult<'_>,
3294 position: Offset,
3295 ) -> bool {
3296 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3297 }
3298
3299 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3300 self.as_box().get_max_intrinsic_width(app, height)
3301 }
3302
3303 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3304 let Some(child) = self.child(app) else {
3305 return 0.0;
3306 };
3307 let width = child.get_max_intrinsic_width(app, height);
3308 apply_step(width, self.get(app).step_width)
3309 }
3310
3311 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3312 let Some(child) = self.child(app) else {
3313 return 0.0;
3314 };
3315 let width = if width.is_finite() {
3316 width
3317 } else {
3318 self.as_box().get_max_intrinsic_width(app, f64::INFINITY)
3319 };
3320 debug_assert!(width.is_finite());
3321 let height = child.get_min_intrinsic_height(app, width);
3322 apply_step(height, self.get(app).step_height)
3323 }
3324
3325 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3326 let Some(child) = self.child(app) else {
3327 return 0.0;
3328 };
3329 let width = if width.is_finite() {
3330 width
3331 } else {
3332 self.as_box().get_max_intrinsic_width(app, f64::INFINITY)
3333 };
3334 debug_assert!(width.is_finite());
3335 let height = child.get_max_intrinsic_height(app, width);
3336 apply_step(height, self.get(app).step_height)
3337 }
3338
3339 fn compute_distance_to_actual_baseline(
3340 self: RenderHandle<Self>,
3341 app: &mut App,
3342 baseline: TextBaseline,
3343 ) -> Option<f64> {
3344 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3345 }
3346
3347 fn compute_dry_layout(
3348 self: RenderHandle<Self>,
3349 app: &mut App,
3350 constraints: BoxConstraints,
3351 ) -> Size {
3352 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
3353 }
3354
3355 fn compute_dry_baseline(
3356 self: RenderHandle<Self>,
3357 app: &mut App,
3358 constraints: BoxConstraints,
3359 baseline: TextBaseline,
3360 ) -> Option<f64> {
3361 let child = self.child(app)?;
3362 let child_constraints = self.child_constraints(app, child, constraints);
3363 child.get_dry_baseline(app, child_constraints, baseline)
3364 }
3365}
3366
3367pub struct RenderIntrinsicHeight {
3383 render_object: RenderObjectData,
3384 render_box: RenderBoxData,
3385 child: RenderObjectWithChildData<AnyRenderBox>,
3386}
3387
3388impl RenderIntrinsicHeight {
3389 pub fn new(app: &mut App, child: Option<AnyRenderBox>) -> RenderHandle<RenderIntrinsicHeight> {
3391 let this = RenderHandle::new_box(
3392 app,
3393 RenderIntrinsicHeight {
3394 render_object: RenderObjectData::new(),
3395 render_box: RenderBoxData::new(),
3396 child: RenderObjectWithChildData::new(),
3397 },
3398 );
3399 this.set_child(app, child);
3400 this
3401 }
3402
3403 fn child_constraints(
3404 self: RenderHandle<Self>,
3405 app: &mut App,
3406 child: AnyRenderBox,
3407 constraints: BoxConstraints,
3408 ) -> BoxConstraints {
3409 if constraints.has_tight_height() {
3410 return constraints;
3411 }
3412 let height = child.get_max_intrinsic_height(app, constraints.max_width);
3413 constraints.tighten(None, Some(height))
3414 }
3415
3416 fn compute_size(
3418 self: RenderHandle<Self>,
3419 app: &mut App,
3420 constraints: BoxConstraints,
3421 layout_child: ChildLayouter,
3422 ) -> Size {
3423 match self.child(app) {
3424 Some(child) => {
3425 let child_constraints = self.child_constraints(app, child, constraints);
3426 layout_child(app, child, child_constraints)
3427 }
3428 None => constraints.smallest(),
3429 }
3430 }
3431}
3432
3433impl RenderObjectWithChildMixin for RenderIntrinsicHeight {
3434 type ChildType = AnyRenderBox;
3435
3436 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3437 &self.get(app).child
3438 }
3439
3440 fn child_data_mut(
3441 self: RenderHandle<Self>,
3442 app: &mut App,
3443 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3444 &mut self.get_mut(app).child
3445 }
3446}
3447
3448impl RenderProxyBoxMixin for RenderIntrinsicHeight {}
3449
3450impl RenderObject for RenderIntrinsicHeight {
3451 crate::render_object_accessors!();
3452
3453 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3454 let constraints = self.constraints(app);
3455 let size = self.compute_size(app, constraints, ChildLayoutHelper::layout_child);
3456 self.set_size(app, size);
3457 }
3458
3459 fn paint(
3460 self: RenderHandle<Self>,
3461 app: &mut App,
3462 context: &mut PaintingContext,
3463 offset: Offset,
3464 ) {
3465 RenderProxyBoxMixin::paint(self, app, context, offset);
3466 }
3467
3468 fn visit_children(
3469 self: RenderHandle<Self>,
3470 app: &App,
3471 visitor: &mut dyn FnMut(AnyRenderObject),
3472 ) {
3473 if let Some(child) = self.child(app) {
3474 visitor(child.as_object());
3475 }
3476 }
3477}
3478
3479impl RenderBox for RenderIntrinsicHeight {
3480 crate::render_box_accessors!();
3481
3482 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3483 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3484 }
3485
3486 fn apply_paint_transform(
3487 self: RenderHandle<Self>,
3488 app: &App,
3489 child: AnyRenderObject,
3490 transform: &mut Matrix4,
3491 ) {
3492 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3493 }
3494
3495 fn hit_test_children(
3496 self: RenderHandle<Self>,
3497 app: &mut App,
3498 result: &mut BoxHitTestResult<'_>,
3499 position: Offset,
3500 ) -> bool {
3501 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
3502 }
3503
3504 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3505 let Some(child) = self.child(app) else {
3506 return 0.0;
3507 };
3508 let height = if height.is_finite() {
3509 height
3510 } else {
3511 child.get_max_intrinsic_height(app, f64::INFINITY)
3512 };
3513 debug_assert!(height.is_finite());
3514 child.get_min_intrinsic_width(app, height)
3515 }
3516
3517 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
3518 let Some(child) = self.child(app) else {
3519 return 0.0;
3520 };
3521 let height = if height.is_finite() {
3522 height
3523 } else {
3524 child.get_max_intrinsic_height(app, f64::INFINITY)
3525 };
3526 debug_assert!(height.is_finite());
3527 child.get_max_intrinsic_width(app, height)
3528 }
3529
3530 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3531 self.as_box().get_max_intrinsic_height(app, width)
3532 }
3533
3534 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
3535 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
3536 }
3537
3538 fn compute_distance_to_actual_baseline(
3539 self: RenderHandle<Self>,
3540 app: &mut App,
3541 baseline: TextBaseline,
3542 ) -> Option<f64> {
3543 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
3544 }
3545
3546 fn compute_dry_layout(
3547 self: RenderHandle<Self>,
3548 app: &mut App,
3549 constraints: BoxConstraints,
3550 ) -> Size {
3551 self.compute_size(app, constraints, ChildLayoutHelper::dry_layout_child)
3552 }
3553
3554 fn compute_dry_baseline(
3555 self: RenderHandle<Self>,
3556 app: &mut App,
3557 constraints: BoxConstraints,
3558 baseline: TextBaseline,
3559 ) -> Option<f64> {
3560 let child = self.child(app)?;
3561 let child_constraints = self.child_constraints(app, child, constraints);
3562 child.get_dry_baseline(app, child_constraints, baseline)
3563 }
3564}
3565
3566pub trait CustomClipper<T>: 'static {
3580 fn reclip(&self) -> Option<&Rc<dyn Listenable>> {
3586 None
3587 }
3588
3589 fn get_clip(&self, size: Size) -> T;
3592
3593 fn should_reclip(&self, old_clipper: &dyn CustomClipper<T>) -> bool;
3611
3612 fn as_any(&self) -> &dyn Any;
3614}
3615
3616impl<T: 'static> Listenable for dyn CustomClipper<T> {
3617 fn add_listener(&self, app: &mut App, listener: Listener) {
3621 if let Some(reclip) = self.reclip() {
3622 reclip.add_listener(app, listener);
3623 }
3624 }
3625
3626 fn remove_listener(&self, app: &mut App, listener: &Listener) {
3629 if let Some(reclip) = self.reclip() {
3630 reclip.remove_listener(app, listener);
3631 }
3632 }
3633}
3634
3635pub struct RenderCustomClipData<T> {
3637 clipper: Option<Rc<dyn CustomClipper<T>>>,
3638 clip: Option<T>,
3639 clip_behavior: Clip,
3640}
3641
3642impl<T> RenderCustomClipData<T> {
3643 pub fn new(
3645 clipper: Option<Rc<dyn CustomClipper<T>>>,
3646 clip_behavior: Clip,
3647 ) -> RenderCustomClipData<T> {
3648 RenderCustomClipData {
3649 clipper,
3650 clip: None,
3651 clip_behavior,
3652 }
3653 }
3654}
3655
3656pub struct ShapeBorderClipper {
3658 pub shape: Box<dyn ShapeBorder>,
3660 pub text_direction: Option<TextDirection>,
3665}
3666
3667impl ShapeBorderClipper {
3668 pub fn new(shape: Box<dyn ShapeBorder>, text_direction: Option<TextDirection>) -> Self {
3675 ShapeBorderClipper {
3676 shape,
3677 text_direction,
3678 }
3679 }
3680}
3681
3682impl CustomClipper<Arc<Path>> for ShapeBorderClipper {
3683 fn get_clip(&self, size: Size) -> Arc<Path> {
3684 self.shape
3685 .get_outer_path(Offset::ZERO & size, self.text_direction)
3686 }
3687
3688 fn should_reclip(&self, old_clipper: &dyn CustomClipper<Arc<Path>>) -> bool {
3689 let Some(old_clipper) = old_clipper.as_any().downcast_ref::<ShapeBorderClipper>() else {
3690 return true;
3691 };
3692 !old_clipper.shape.eq_shape(&*self.shape)
3693 || old_clipper.text_direction != self.text_direction
3694 }
3695
3696 fn as_any(&self) -> &dyn Any {
3697 self
3698 }
3699}
3700
3701pub trait RenderCustomClip<T: Clone + 'static>: RenderProxyBoxMixin {
3707 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<T>;
3709
3710 fn custom_clip_data_mut(
3712 self: RenderHandle<Self>,
3713 app: &mut App,
3714 ) -> &mut RenderCustomClipData<T>;
3715
3716 fn default_clip(self: RenderHandle<Self>, app: &App) -> T;
3718
3719 fn clipper(self: RenderHandle<Self>, app: &App) -> Option<Rc<dyn CustomClipper<T>>> {
3721 self.custom_clip_data(app).clipper.clone()
3722 }
3723
3724 fn set_clipper(
3726 self: RenderHandle<Self>,
3727 app: &mut App,
3728 new_clipper: Option<Rc<dyn CustomClipper<T>>>,
3729 ) {
3730 let old_clipper = self.clipper(app);
3731 if same_instance(old_clipper.as_ref(), new_clipper.as_ref()) {
3732 return;
3733 }
3734 self.custom_clip_data_mut(app).clipper = new_clipper.clone();
3735 debug_assert!(new_clipper.is_some() || old_clipper.is_some());
3736 let reclip = match (&new_clipper, &old_clipper) {
3737 (Some(new_clipper), Some(old_clipper)) => {
3738 new_clipper.as_any().type_id() != old_clipper.as_any().type_id()
3739 || new_clipper.should_reclip(&**old_clipper)
3740 }
3741 _ => true,
3742 };
3743 if reclip {
3744 self.mark_needs_clip(app);
3745 }
3746 if self.attached(app) {
3747 if let Some(old_clipper) = &old_clipper {
3748 old_clipper.remove_listener(app, &self.clip_listener());
3749 }
3750 if let Some(new_clipper) = &new_clipper {
3751 new_clipper.add_listener(app, self.clip_listener());
3752 }
3753 }
3754 }
3755
3756 fn did_attach(self: RenderHandle<Self>, app: &mut App) {
3758 if let Some(clipper) = self.clipper(app) {
3759 clipper.add_listener(app, self.clip_listener());
3760 }
3761 }
3762
3763 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
3765 if let Some(clipper) = self.clipper(app) {
3766 clipper.remove_listener(app, &self.clip_listener());
3767 }
3768 }
3769
3770 fn mark_needs_clip(self: RenderHandle<Self>, app: &mut App) {
3772 self.custom_clip_data_mut(app).clip = None;
3773 self.mark_needs_paint(app);
3774 }
3775
3776 fn clip_listener(self: RenderHandle<Self>) -> Listener {
3778 Listener::handle_method(self.handle(), mark_needs_clip::<Self, T>)
3779 }
3780
3781 fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
3783 self.custom_clip_data(app).clip_behavior
3784 }
3785
3786 fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
3788 if value != self.clip_behavior(app) {
3789 self.custom_clip_data_mut(app).clip_behavior = value;
3790 self.mark_needs_paint(app);
3791 }
3792 }
3793
3794 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3796 let old_size = self.has_size(app).then(|| self.size(app));
3797 RenderProxyBoxMixin::perform_layout(self, app);
3798 if old_size != Some(self.size(app)) {
3799 self.custom_clip_data_mut(app).clip = None;
3800 }
3801 }
3802
3803 fn update_clip(self: RenderHandle<Self>, app: &mut App) {
3805 if self.custom_clip_data(app).clip.is_some() {
3806 return;
3807 }
3808 let clip = match self.clipper(app) {
3809 Some(clipper) => clipper.get_clip(self.size(app)),
3810 None => self.default_clip(app),
3811 };
3812 self.custom_clip_data_mut(app).clip = Some(clip);
3813 }
3814
3815 fn clip(self: RenderHandle<Self>, app: &App) -> T {
3817 self.custom_clip_data(app)
3818 .clip
3819 .clone()
3820 .expect("update_clip computes the clip")
3821 }
3822}
3823
3824fn mark_needs_clip<C: RenderCustomClip<T>, T: Clone + 'static>(this: Handle<C>, app: &mut App) {
3825 RenderCustomClip::mark_needs_clip(RenderHandle::from_handle(this), app);
3826}
3827
3828pub struct RenderClipRect {
3834 render_object: RenderObjectData,
3835 render_box: RenderBoxData,
3836 child: RenderObjectWithChildData<AnyRenderBox>,
3837 custom_clip: RenderCustomClipData<Rect>,
3838}
3839
3840impl RenderClipRect {
3841 pub fn new(
3848 app: &mut App,
3849 clipper: Option<Rc<dyn CustomClipper<Rect>>>,
3850 clip_behavior: Clip,
3851 child: Option<AnyRenderBox>,
3852 ) -> RenderHandle<RenderClipRect> {
3853 let this = RenderHandle::new_box(
3854 app,
3855 RenderClipRect {
3856 render_object: RenderObjectData::new(),
3857 render_box: RenderBoxData::new(),
3858 child: RenderObjectWithChildData::new(),
3859 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
3860 },
3861 );
3862 this.set_child(app, child);
3863 this
3864 }
3865}
3866
3867impl RenderObjectWithChildMixin for RenderClipRect {
3868 type ChildType = AnyRenderBox;
3869
3870 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
3871 &self.get(app).child
3872 }
3873
3874 fn child_data_mut(
3875 self: RenderHandle<Self>,
3876 app: &mut App,
3877 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
3878 &mut self.get_mut(app).child
3879 }
3880}
3881
3882impl RenderProxyBoxMixin for RenderClipRect {}
3883
3884impl RenderCustomClip<Rect> for RenderClipRect {
3885 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Rect> {
3886 &self.get(app).custom_clip
3887 }
3888
3889 fn custom_clip_data_mut(
3890 self: RenderHandle<Self>,
3891 app: &mut App,
3892 ) -> &mut RenderCustomClipData<Rect> {
3893 &mut self.get_mut(app).custom_clip
3894 }
3895
3896 fn default_clip(self: RenderHandle<Self>, app: &App) -> Rect {
3897 Offset::ZERO & self.size(app)
3898 }
3899}
3900
3901impl RenderObject for RenderClipRect {
3902 crate::render_object_accessors!();
3903
3904 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
3905 if let Some(child) = self.child(app) {
3906 child.as_object().attach(app, owner);
3907 }
3908 RenderCustomClip::did_attach(self, app);
3909 }
3910
3911 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
3912 RenderCustomClip::did_detach(self, app);
3913 if let Some(child) = self.child(app) {
3914 child.as_object().detach(app);
3915 }
3916 }
3917
3918 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
3919 RenderCustomClip::perform_layout(self, app);
3920 }
3921
3922 fn paint(
3923 self: RenderHandle<Self>,
3924 app: &mut App,
3925 context: &mut PaintingContext,
3926 offset: Offset,
3927 ) {
3928 if let Some(child) = self.child(app) {
3929 let clip_behavior = self.clip_behavior(app);
3930 if clip_behavior != Clip::None {
3931 self.update_clip(app);
3932 let clip = self.clip(app);
3933 let old = self.as_object().layer_as::<ClipRectLayer>(app);
3934 let layer = context.push_clip_rect(
3935 app,
3936 self.as_object().needs_compositing(app),
3937 offset,
3938 clip,
3939 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
3940 clip_behavior,
3941 old,
3942 );
3943 self.as_object()
3944 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
3945 } else {
3946 context.paint_child(app, child.as_object(), offset);
3947 self.as_object().set_layer(app, None);
3948 }
3949 } else {
3950 self.as_object().set_layer(app, None);
3951 }
3952 }
3953
3954 fn visit_children(
3955 self: RenderHandle<Self>,
3956 app: &App,
3957 visitor: &mut dyn FnMut(AnyRenderObject),
3958 ) {
3959 if let Some(child) = self.child(app) {
3960 visitor(child.as_object());
3961 }
3962 }
3963}
3964
3965impl RenderBox for RenderClipRect {
3966 crate::render_box_accessors!();
3967
3968 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
3969 RenderProxyBoxMixin::setup_parent_data(self, app, child);
3970 }
3971
3972 fn apply_paint_transform(
3973 self: RenderHandle<Self>,
3974 app: &App,
3975 child: AnyRenderObject,
3976 transform: &mut Matrix4,
3977 ) {
3978 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
3979 }
3980
3981 fn hit_test(
3982 self: RenderHandle<Self>,
3983 app: &mut App,
3984 result: &mut BoxHitTestResult<'_>,
3985 position: Offset,
3986 ) -> bool {
3987 if self.clipper(app).is_some() {
3988 self.update_clip(app);
3989 if !self.clip(app).contains(position) {
3990 return false;
3991 }
3992 }
3993 RenderBoxBase::hit_test(self, app, result, position)
3994 }
3995
3996 fn hit_test_children(
3997 self: RenderHandle<Self>,
3998 app: &mut App,
3999 result: &mut BoxHitTestResult<'_>,
4000 position: Offset,
4001 ) -> bool {
4002 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4003 }
4004
4005 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4006 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4007 }
4008
4009 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4010 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4011 }
4012
4013 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4014 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4015 }
4016
4017 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4018 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4019 }
4020
4021 fn compute_distance_to_actual_baseline(
4022 self: RenderHandle<Self>,
4023 app: &mut App,
4024 baseline: TextBaseline,
4025 ) -> Option<f64> {
4026 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4027 }
4028
4029 fn compute_dry_baseline(
4030 self: RenderHandle<Self>,
4031 app: &mut App,
4032 constraints: BoxConstraints,
4033 baseline: TextBaseline,
4034 ) -> Option<f64> {
4035 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4036 }
4037
4038 fn compute_dry_layout(
4039 self: RenderHandle<Self>,
4040 app: &mut App,
4041 constraints: BoxConstraints,
4042 ) -> Size {
4043 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4044 }
4045}
4046
4047pub struct RenderClipRRect {
4053 render_object: RenderObjectData,
4054 render_box: RenderBoxData,
4055 child: RenderObjectWithChildData<AnyRenderBox>,
4056 custom_clip: RenderCustomClipData<RRect>,
4057 border_radius: BorderRadiusGeometry,
4058 text_direction: Option<TextDirection>,
4059}
4060
4061impl RenderClipRRect {
4062 pub fn new(
4071 app: &mut App,
4072 border_radius: BorderRadiusGeometry,
4073 clipper: Option<Rc<dyn CustomClipper<RRect>>>,
4074 clip_behavior: Clip,
4075 text_direction: Option<TextDirection>,
4076 child: Option<AnyRenderBox>,
4077 ) -> RenderHandle<RenderClipRRect> {
4078 let this = RenderHandle::new_box(
4079 app,
4080 RenderClipRRect {
4081 render_object: RenderObjectData::new(),
4082 render_box: RenderBoxData::new(),
4083 child: RenderObjectWithChildData::new(),
4084 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4085 border_radius,
4086 text_direction,
4087 },
4088 );
4089 this.set_child(app, child);
4090 this
4091 }
4092
4093 pub fn border_radius(self: RenderHandle<Self>, app: &App) -> BorderRadiusGeometry {
4100 self.get(app).border_radius
4101 }
4102
4103 pub fn set_border_radius(self: RenderHandle<Self>, app: &mut App, value: BorderRadiusGeometry) {
4105 if self.get(app).border_radius == value {
4106 return;
4107 }
4108 self.get_mut(app).border_radius = value;
4109 self.mark_needs_clip(app);
4110 }
4111
4112 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
4114 self.get(app).text_direction
4115 }
4116
4117 pub fn set_text_direction(
4119 self: RenderHandle<Self>,
4120 app: &mut App,
4121 value: Option<TextDirection>,
4122 ) {
4123 if self.get(app).text_direction == value {
4124 return;
4125 }
4126 self.get_mut(app).text_direction = value;
4127 self.mark_needs_clip(app);
4128 }
4129}
4130
4131impl RenderObjectWithChildMixin for RenderClipRRect {
4132 type ChildType = AnyRenderBox;
4133
4134 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4135 &self.get(app).child
4136 }
4137
4138 fn child_data_mut(
4139 self: RenderHandle<Self>,
4140 app: &mut App,
4141 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4142 &mut self.get_mut(app).child
4143 }
4144}
4145
4146impl RenderProxyBoxMixin for RenderClipRRect {}
4147
4148impl RenderCustomClip<RRect> for RenderClipRRect {
4149 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<RRect> {
4150 &self.get(app).custom_clip
4151 }
4152
4153 fn custom_clip_data_mut(
4154 self: RenderHandle<Self>,
4155 app: &mut App,
4156 ) -> &mut RenderCustomClipData<RRect> {
4157 &mut self.get_mut(app).custom_clip
4158 }
4159
4160 fn default_clip(self: RenderHandle<Self>, app: &App) -> RRect {
4161 let this = self.get(app);
4162 this.border_radius
4163 .resolve(this.text_direction)
4164 .to_rrect(Offset::ZERO & self.size(app))
4165 }
4166}
4167
4168impl RenderObject for RenderClipRRect {
4169 crate::render_object_accessors!();
4170
4171 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4172 if let Some(child) = self.child(app) {
4173 child.as_object().attach(app, owner);
4174 }
4175 RenderCustomClip::did_attach(self, app);
4176 }
4177
4178 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4179 RenderCustomClip::did_detach(self, app);
4180 if let Some(child) = self.child(app) {
4181 child.as_object().detach(app);
4182 }
4183 }
4184
4185 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4186 RenderCustomClip::perform_layout(self, app);
4187 }
4188
4189 fn paint(
4190 self: RenderHandle<Self>,
4191 app: &mut App,
4192 context: &mut PaintingContext,
4193 offset: Offset,
4194 ) {
4195 if let Some(child) = self.child(app) {
4196 let clip_behavior = self.clip_behavior(app);
4197 if clip_behavior != Clip::None {
4198 self.update_clip(app);
4199 let clip = self.clip(app);
4200 let old = self.as_object().layer_as::<ClipRRectLayer>(app);
4201 let layer = context.push_clip_rrect(
4202 app,
4203 self.as_object().needs_compositing(app),
4204 offset,
4205 clip.outer_rect(),
4206 clip,
4207 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4208 clip_behavior,
4209 old,
4210 );
4211 self.as_object()
4212 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4213 } else {
4214 context.paint_child(app, child.as_object(), offset);
4215 self.as_object().set_layer(app, None);
4216 }
4217 } else {
4218 self.as_object().set_layer(app, None);
4219 }
4220 }
4221
4222 fn visit_children(
4223 self: RenderHandle<Self>,
4224 app: &App,
4225 visitor: &mut dyn FnMut(AnyRenderObject),
4226 ) {
4227 if let Some(child) = self.child(app) {
4228 visitor(child.as_object());
4229 }
4230 }
4231}
4232
4233impl RenderBox for RenderClipRRect {
4234 crate::render_box_accessors!();
4235
4236 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4237 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4238 }
4239
4240 fn apply_paint_transform(
4241 self: RenderHandle<Self>,
4242 app: &App,
4243 child: AnyRenderObject,
4244 transform: &mut Matrix4,
4245 ) {
4246 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4247 }
4248
4249 fn hit_test(
4250 self: RenderHandle<Self>,
4251 app: &mut App,
4252 result: &mut BoxHitTestResult<'_>,
4253 position: Offset,
4254 ) -> bool {
4255 if self.clipper(app).is_some() {
4256 self.update_clip(app);
4257 if !self.clip(app).contains(position) {
4258 return false;
4259 }
4260 }
4261 RenderBoxBase::hit_test(self, app, result, position)
4262 }
4263
4264 fn hit_test_children(
4265 self: RenderHandle<Self>,
4266 app: &mut App,
4267 result: &mut BoxHitTestResult<'_>,
4268 position: Offset,
4269 ) -> bool {
4270 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4271 }
4272
4273 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4274 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4275 }
4276
4277 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4278 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4279 }
4280
4281 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4282 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4283 }
4284
4285 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4286 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4287 }
4288
4289 fn compute_distance_to_actual_baseline(
4290 self: RenderHandle<Self>,
4291 app: &mut App,
4292 baseline: TextBaseline,
4293 ) -> Option<f64> {
4294 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4295 }
4296
4297 fn compute_dry_baseline(
4298 self: RenderHandle<Self>,
4299 app: &mut App,
4300 constraints: BoxConstraints,
4301 baseline: TextBaseline,
4302 ) -> Option<f64> {
4303 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4304 }
4305
4306 fn compute_dry_layout(
4307 self: RenderHandle<Self>,
4308 app: &mut App,
4309 constraints: BoxConstraints,
4310 ) -> Size {
4311 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4312 }
4313}
4314
4315pub struct RenderClipOval {
4320 render_object: RenderObjectData,
4321 render_box: RenderBoxData,
4322 child: RenderObjectWithChildData<AnyRenderBox>,
4323 custom_clip: RenderCustomClipData<Rect>,
4324 cached_rect: Option<Rect>,
4325 cached_path: Option<Arc<Path>>,
4326}
4327
4328impl RenderClipOval {
4329 pub fn new(
4336 app: &mut App,
4337 clipper: Option<Rc<dyn CustomClipper<Rect>>>,
4338 clip_behavior: Clip,
4339 child: Option<AnyRenderBox>,
4340 ) -> RenderHandle<RenderClipOval> {
4341 let this = RenderHandle::new_box(
4342 app,
4343 RenderClipOval {
4344 render_object: RenderObjectData::new(),
4345 render_box: RenderBoxData::new(),
4346 child: RenderObjectWithChildData::new(),
4347 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4348 cached_rect: None,
4349 cached_path: None,
4350 },
4351 );
4352 this.set_child(app, child);
4353 this
4354 }
4355
4356 fn get_clip_path(self: RenderHandle<Self>, app: &mut App, rect: Rect) -> Arc<Path> {
4357 if self.get(app).cached_rect != Some(rect) {
4358 let radius = [(rect.width() / 2.0) as f32, (rect.height() / 2.0) as f32];
4359 let mut path = PathBuilder::new();
4360 path.rrect_radii_elliptical(rect, [radius; 4]);
4361 let this = self.get_mut(app);
4362 this.cached_rect = Some(rect);
4363 this.cached_path = Some(path.build());
4364 }
4365 self.get(app).cached_path.clone().expect("cached above")
4366 }
4367}
4368
4369impl RenderObjectWithChildMixin for RenderClipOval {
4370 type ChildType = AnyRenderBox;
4371
4372 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4373 &self.get(app).child
4374 }
4375
4376 fn child_data_mut(
4377 self: RenderHandle<Self>,
4378 app: &mut App,
4379 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4380 &mut self.get_mut(app).child
4381 }
4382}
4383
4384impl RenderProxyBoxMixin for RenderClipOval {}
4385
4386impl RenderCustomClip<Rect> for RenderClipOval {
4387 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Rect> {
4388 &self.get(app).custom_clip
4389 }
4390
4391 fn custom_clip_data_mut(
4392 self: RenderHandle<Self>,
4393 app: &mut App,
4394 ) -> &mut RenderCustomClipData<Rect> {
4395 &mut self.get_mut(app).custom_clip
4396 }
4397
4398 fn default_clip(self: RenderHandle<Self>, app: &App) -> Rect {
4399 Offset::ZERO & self.size(app)
4400 }
4401}
4402
4403impl RenderObject for RenderClipOval {
4404 crate::render_object_accessors!();
4405
4406 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4407 if let Some(child) = self.child(app) {
4408 child.as_object().attach(app, owner);
4409 }
4410 RenderCustomClip::did_attach(self, app);
4411 }
4412
4413 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4414 RenderCustomClip::did_detach(self, app);
4415 if let Some(child) = self.child(app) {
4416 child.as_object().detach(app);
4417 }
4418 }
4419
4420 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4421 RenderCustomClip::perform_layout(self, app);
4422 }
4423
4424 fn paint(
4425 self: RenderHandle<Self>,
4426 app: &mut App,
4427 context: &mut PaintingContext,
4428 offset: Offset,
4429 ) {
4430 if let Some(child) = self.child(app) {
4431 let clip_behavior = self.clip_behavior(app);
4432 if clip_behavior != Clip::None {
4433 self.update_clip(app);
4434 let clip = self.clip(app);
4435 let clip_path = self.get_clip_path(app, clip);
4436 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4437 let layer = context.push_clip_path(
4438 app,
4439 self.as_object().needs_compositing(app),
4440 offset,
4441 clip,
4442 clip_path,
4443 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4444 clip_behavior,
4445 old,
4446 );
4447 self.as_object()
4448 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4449 } else {
4450 context.paint_child(app, child.as_object(), offset);
4451 self.as_object().set_layer(app, None);
4452 }
4453 } else {
4454 self.as_object().set_layer(app, None);
4455 }
4456 }
4457
4458 fn visit_children(
4459 self: RenderHandle<Self>,
4460 app: &App,
4461 visitor: &mut dyn FnMut(AnyRenderObject),
4462 ) {
4463 if let Some(child) = self.child(app) {
4464 visitor(child.as_object());
4465 }
4466 }
4467}
4468
4469impl RenderBox for RenderClipOval {
4470 crate::render_box_accessors!();
4471
4472 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4473 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4474 }
4475
4476 fn apply_paint_transform(
4477 self: RenderHandle<Self>,
4478 app: &App,
4479 child: AnyRenderObject,
4480 transform: &mut Matrix4,
4481 ) {
4482 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4483 }
4484
4485 fn hit_test(
4486 self: RenderHandle<Self>,
4487 app: &mut App,
4488 result: &mut BoxHitTestResult<'_>,
4489 position: Offset,
4490 ) -> bool {
4491 self.update_clip(app);
4492 let clip = self.clip(app);
4493 let center = clip.center();
4494 let offset = Offset::new(
4496 (position.dx() - center.dx()) / clip.width(),
4497 (position.dy() - center.dy()) / clip.height(),
4498 );
4499 if offset.distance_squared() > 0.25 {
4501 return false;
4503 }
4504 RenderBoxBase::hit_test(self, app, result, position)
4505 }
4506
4507 fn hit_test_children(
4508 self: RenderHandle<Self>,
4509 app: &mut App,
4510 result: &mut BoxHitTestResult<'_>,
4511 position: Offset,
4512 ) -> bool {
4513 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4514 }
4515
4516 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4517 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4518 }
4519
4520 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4521 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4522 }
4523
4524 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4525 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4526 }
4527
4528 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4529 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4530 }
4531
4532 fn compute_distance_to_actual_baseline(
4533 self: RenderHandle<Self>,
4534 app: &mut App,
4535 baseline: TextBaseline,
4536 ) -> Option<f64> {
4537 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4538 }
4539
4540 fn compute_dry_baseline(
4541 self: RenderHandle<Self>,
4542 app: &mut App,
4543 constraints: BoxConstraints,
4544 baseline: TextBaseline,
4545 ) -> Option<f64> {
4546 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4547 }
4548
4549 fn compute_dry_layout(
4550 self: RenderHandle<Self>,
4551 app: &mut App,
4552 constraints: BoxConstraints,
4553 ) -> Size {
4554 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4555 }
4556}
4557
4558pub struct RenderClipPath {
4570 render_object: RenderObjectData,
4571 render_box: RenderBoxData,
4572 child: RenderObjectWithChildData<AnyRenderBox>,
4573 custom_clip: RenderCustomClipData<Arc<Path>>,
4574}
4575
4576impl RenderClipPath {
4577 pub fn new(
4586 app: &mut App,
4587 clipper: Option<Rc<dyn CustomClipper<Arc<Path>>>>,
4588 clip_behavior: Clip,
4589 child: Option<AnyRenderBox>,
4590 ) -> RenderHandle<RenderClipPath> {
4591 let this = RenderHandle::new_box(
4592 app,
4593 RenderClipPath {
4594 render_object: RenderObjectData::new(),
4595 render_box: RenderBoxData::new(),
4596 child: RenderObjectWithChildData::new(),
4597 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4598 },
4599 );
4600 this.set_child(app, child);
4601 this
4602 }
4603}
4604
4605impl RenderObjectWithChildMixin for RenderClipPath {
4606 type ChildType = AnyRenderBox;
4607
4608 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4609 &self.get(app).child
4610 }
4611
4612 fn child_data_mut(
4613 self: RenderHandle<Self>,
4614 app: &mut App,
4615 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4616 &mut self.get_mut(app).child
4617 }
4618}
4619
4620impl RenderProxyBoxMixin for RenderClipPath {}
4621
4622impl RenderCustomClip<Arc<Path>> for RenderClipPath {
4623 fn custom_clip_data(self: RenderHandle<Self>, app: &App) -> &RenderCustomClipData<Arc<Path>> {
4624 &self.get(app).custom_clip
4625 }
4626
4627 fn custom_clip_data_mut(
4628 self: RenderHandle<Self>,
4629 app: &mut App,
4630 ) -> &mut RenderCustomClipData<Arc<Path>> {
4631 &mut self.get_mut(app).custom_clip
4632 }
4633
4634 fn default_clip(self: RenderHandle<Self>, app: &App) -> Arc<Path> {
4635 let mut path = PathBuilder::new();
4636 path.rect((Offset::ZERO & self.size(app)).into());
4637 path.build()
4638 }
4639}
4640
4641impl RenderObject for RenderClipPath {
4642 crate::render_object_accessors!();
4643
4644 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4645 if let Some(child) = self.child(app) {
4646 child.as_object().attach(app, owner);
4647 }
4648 RenderCustomClip::did_attach(self, app);
4649 }
4650
4651 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4652 RenderCustomClip::did_detach(self, app);
4653 if let Some(child) = self.child(app) {
4654 child.as_object().detach(app);
4655 }
4656 }
4657
4658 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4659 RenderCustomClip::perform_layout(self, app);
4660 }
4661
4662 fn paint(
4663 self: RenderHandle<Self>,
4664 app: &mut App,
4665 context: &mut PaintingContext,
4666 offset: Offset,
4667 ) {
4668 if let Some(child) = self.child(app) {
4669 let clip_behavior = self.clip_behavior(app);
4670 if clip_behavior != Clip::None {
4671 self.update_clip(app);
4672 let clip = self.clip(app);
4673 let bounds = Offset::ZERO & self.size(app);
4674 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4675 let layer = context.push_clip_path(
4676 app,
4677 self.as_object().needs_compositing(app),
4678 offset,
4679 bounds,
4680 clip,
4681 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4682 clip_behavior,
4683 old,
4684 );
4685 self.as_object()
4686 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4687 } else {
4688 context.paint_child(app, child.as_object(), offset);
4689 self.as_object().set_layer(app, None);
4690 }
4691 } else {
4692 self.as_object().set_layer(app, None);
4693 }
4694 }
4695
4696 fn visit_children(
4697 self: RenderHandle<Self>,
4698 app: &App,
4699 visitor: &mut dyn FnMut(AnyRenderObject),
4700 ) {
4701 if let Some(child) = self.child(app) {
4702 visitor(child.as_object());
4703 }
4704 }
4705}
4706
4707impl RenderBox for RenderClipPath {
4708 crate::render_box_accessors!();
4709
4710 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4711 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4712 }
4713
4714 fn apply_paint_transform(
4715 self: RenderHandle<Self>,
4716 app: &App,
4717 child: AnyRenderObject,
4718 transform: &mut Matrix4,
4719 ) {
4720 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4721 }
4722
4723 fn hit_test(
4724 self: RenderHandle<Self>,
4725 app: &mut App,
4726 result: &mut BoxHitTestResult<'_>,
4727 position: Offset,
4728 ) -> bool {
4729 if self.clipper(app).is_some() {
4730 self.update_clip(app);
4731 let point = Point::new(position.dx() as f32, position.dy() as f32);
4732 if !self.clip(app).contains(point, FillRule::NonZero) {
4733 return false;
4734 }
4735 }
4736 RenderBoxBase::hit_test(self, app, result, position)
4737 }
4738
4739 fn hit_test_children(
4740 self: RenderHandle<Self>,
4741 app: &mut App,
4742 result: &mut BoxHitTestResult<'_>,
4743 position: Offset,
4744 ) -> bool {
4745 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
4746 }
4747
4748 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4749 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
4750 }
4751
4752 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
4753 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
4754 }
4755
4756 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4757 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
4758 }
4759
4760 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
4761 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
4762 }
4763
4764 fn compute_distance_to_actual_baseline(
4765 self: RenderHandle<Self>,
4766 app: &mut App,
4767 baseline: TextBaseline,
4768 ) -> Option<f64> {
4769 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
4770 }
4771
4772 fn compute_dry_baseline(
4773 self: RenderHandle<Self>,
4774 app: &mut App,
4775 constraints: BoxConstraints,
4776 baseline: TextBaseline,
4777 ) -> Option<f64> {
4778 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
4779 }
4780
4781 fn compute_dry_layout(
4782 self: RenderHandle<Self>,
4783 app: &mut App,
4784 constraints: BoxConstraints,
4785 ) -> Size {
4786 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
4787 }
4788}
4789
4790pub struct RenderClipRSuperellipse {
4796 render_object: RenderObjectData,
4797 render_box: RenderBoxData,
4798 child: RenderObjectWithChildData<AnyRenderBox>,
4799 custom_clip: RenderCustomClipData<RSuperellipse>,
4800 border_radius: BorderRadiusGeometry,
4801 text_direction: Option<TextDirection>,
4802}
4803
4804impl RenderClipRSuperellipse {
4805 pub fn new(
4814 app: &mut App,
4815 border_radius: BorderRadiusGeometry,
4816 clipper: Option<Rc<dyn CustomClipper<RSuperellipse>>>,
4817 clip_behavior: Clip,
4818 text_direction: Option<TextDirection>,
4819 child: Option<AnyRenderBox>,
4820 ) -> RenderHandle<RenderClipRSuperellipse> {
4821 let this = RenderHandle::new_box(
4822 app,
4823 RenderClipRSuperellipse {
4824 render_object: RenderObjectData::new(),
4825 render_box: RenderBoxData::new(),
4826 child: RenderObjectWithChildData::new(),
4827 custom_clip: RenderCustomClipData::new(clipper, clip_behavior),
4828 border_radius,
4829 text_direction,
4830 },
4831 );
4832 this.set_child(app, child);
4833 this
4834 }
4835
4836 pub fn border_radius(self: RenderHandle<Self>, app: &App) -> BorderRadiusGeometry {
4843 self.get(app).border_radius
4844 }
4845
4846 pub fn set_border_radius(self: RenderHandle<Self>, app: &mut App, value: BorderRadiusGeometry) {
4848 if self.get(app).border_radius == value {
4849 return;
4850 }
4851 self.get_mut(app).border_radius = value;
4852 self.mark_needs_clip(app);
4853 }
4854
4855 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
4857 self.get(app).text_direction
4858 }
4859
4860 pub fn set_text_direction(
4862 self: RenderHandle<Self>,
4863 app: &mut App,
4864 value: Option<TextDirection>,
4865 ) {
4866 if self.get(app).text_direction == value {
4867 return;
4868 }
4869 self.get_mut(app).text_direction = value;
4870 self.mark_needs_clip(app);
4871 }
4872}
4873
4874impl RenderObjectWithChildMixin for RenderClipRSuperellipse {
4875 type ChildType = AnyRenderBox;
4876
4877 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
4878 &self.get(app).child
4879 }
4880
4881 fn child_data_mut(
4882 self: RenderHandle<Self>,
4883 app: &mut App,
4884 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
4885 &mut self.get_mut(app).child
4886 }
4887}
4888
4889impl RenderProxyBoxMixin for RenderClipRSuperellipse {}
4890
4891impl RenderCustomClip<RSuperellipse> for RenderClipRSuperellipse {
4892 fn custom_clip_data(
4893 self: RenderHandle<Self>,
4894 app: &App,
4895 ) -> &RenderCustomClipData<RSuperellipse> {
4896 &self.get(app).custom_clip
4897 }
4898
4899 fn custom_clip_data_mut(
4900 self: RenderHandle<Self>,
4901 app: &mut App,
4902 ) -> &mut RenderCustomClipData<RSuperellipse> {
4903 &mut self.get_mut(app).custom_clip
4904 }
4905
4906 fn default_clip(self: RenderHandle<Self>, app: &App) -> RSuperellipse {
4907 let this = self.get(app);
4908 this.border_radius
4909 .resolve(this.text_direction)
4910 .to_r_superellipse(Offset::ZERO & self.size(app))
4911 }
4912}
4913
4914impl RenderObject for RenderClipRSuperellipse {
4915 crate::render_object_accessors!();
4916
4917 fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
4918 if let Some(child) = self.child(app) {
4919 child.as_object().attach(app, owner);
4920 }
4921 RenderCustomClip::did_attach(self, app);
4922 }
4923
4924 fn did_detach(self: RenderHandle<Self>, app: &mut App) {
4925 RenderCustomClip::did_detach(self, app);
4926 if let Some(child) = self.child(app) {
4927 child.as_object().detach(app);
4928 }
4929 }
4930
4931 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
4932 RenderCustomClip::perform_layout(self, app);
4933 }
4934
4935 fn paint(
4936 self: RenderHandle<Self>,
4937 app: &mut App,
4938 context: &mut PaintingContext,
4939 offset: Offset,
4940 ) {
4941 if let Some(child) = self.child(app) {
4942 let clip_behavior = self.clip_behavior(app);
4943 if clip_behavior != Clip::None {
4944 self.update_clip(app);
4945 let clip = self.clip(app);
4946 let mut clip_path = PathBuilder::new();
4947 clip_path.rsuperellipse_radii(
4948 clip.outer_rect().into(),
4949 rsuperellipse_radii_elliptical(clip),
4950 );
4951 let old = self.as_object().layer_as::<ClipPathLayer>(app);
4952 let layer = context.push_clip_path(
4953 app,
4954 self.as_object().needs_compositing(app),
4955 offset,
4956 clip.outer_rect(),
4957 clip_path.build(),
4958 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
4959 clip_behavior,
4960 old,
4961 );
4962 self.as_object()
4963 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
4964 } else {
4965 context.paint_child(app, child.as_object(), offset);
4966 self.as_object().set_layer(app, None);
4967 }
4968 } else {
4969 self.as_object().set_layer(app, None);
4970 }
4971 }
4972
4973 fn visit_children(
4974 self: RenderHandle<Self>,
4975 app: &App,
4976 visitor: &mut dyn FnMut(AnyRenderObject),
4977 ) {
4978 if let Some(child) = self.child(app) {
4979 visitor(child.as_object());
4980 }
4981 }
4982}
4983
4984impl RenderBox for RenderClipRSuperellipse {
4985 crate::render_box_accessors!();
4986
4987 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
4988 RenderProxyBoxMixin::setup_parent_data(self, app, child);
4989 }
4990
4991 fn apply_paint_transform(
4992 self: RenderHandle<Self>,
4993 app: &App,
4994 child: AnyRenderObject,
4995 transform: &mut Matrix4,
4996 ) {
4997 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
4998 }
4999
5000 fn hit_test(
5001 self: RenderHandle<Self>,
5002 app: &mut App,
5003 result: &mut BoxHitTestResult<'_>,
5004 position: Offset,
5005 ) -> bool {
5006 if self.clipper(app).is_some() {
5007 self.update_clip(app);
5008 if !self.clip(app).outer_rect().contains(position) {
5009 return false;
5010 }
5011 }
5012 RenderBoxBase::hit_test(self, app, result, position)
5013 }
5014
5015 fn hit_test_children(
5016 self: RenderHandle<Self>,
5017 app: &mut App,
5018 result: &mut BoxHitTestResult<'_>,
5019 position: Offset,
5020 ) -> bool {
5021 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5022 }
5023
5024 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5025 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5026 }
5027
5028 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5029 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5030 }
5031
5032 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5033 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5034 }
5035
5036 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5037 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5038 }
5039
5040 fn compute_distance_to_actual_baseline(
5041 self: RenderHandle<Self>,
5042 app: &mut App,
5043 baseline: TextBaseline,
5044 ) -> Option<f64> {
5045 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5046 }
5047
5048 fn compute_dry_baseline(
5049 self: RenderHandle<Self>,
5050 app: &mut App,
5051 constraints: BoxConstraints,
5052 baseline: TextBaseline,
5053 ) -> Option<f64> {
5054 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
5055 }
5056
5057 fn compute_dry_layout(
5058 self: RenderHandle<Self>,
5059 app: &mut App,
5060 constraints: BoxConstraints,
5061 ) -> Size {
5062 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
5063 }
5064}
5065
5066pub struct RenderTransform {
5068 render_object: RenderObjectData,
5069 render_box: RenderBoxData,
5070 child: RenderObjectWithChildData<AnyRenderBox>,
5071 origin: Option<Offset>,
5072 alignment: Option<AlignmentGeometry>,
5073 text_direction: Option<TextDirection>,
5074 transform_hit_tests: bool,
5075 transform: Matrix4,
5076}
5077
5078impl RenderTransform {
5079 pub fn new(
5081 app: &mut App,
5082 transform: Matrix4,
5083 origin: Option<Offset>,
5084 alignment: Option<AlignmentGeometry>,
5085 text_direction: Option<TextDirection>,
5086 transform_hit_tests: bool,
5087 child: Option<AnyRenderBox>,
5088 ) -> RenderHandle<RenderTransform> {
5089 let this = RenderHandle::new_box(
5090 app,
5091 RenderTransform {
5092 render_object: RenderObjectData::new(),
5093 render_box: RenderBoxData::new(),
5094 child: RenderObjectWithChildData::new(),
5095 origin,
5096 alignment,
5097 text_direction,
5098 transform_hit_tests,
5099 transform,
5100 },
5101 );
5102 this.set_child(app, child);
5103 this
5104 }
5105
5106 pub fn origin(self: RenderHandle<Self>, app: &App) -> Option<Offset> {
5112 self.get(app).origin
5113 }
5114
5115 pub fn set_origin(self: RenderHandle<Self>, app: &mut App, value: Option<Offset>) {
5117 if self.get(app).origin == value {
5118 return;
5119 }
5120 self.get_mut(app).origin = value;
5121 self.mark_needs_paint(app);
5122 }
5123
5124 pub fn alignment(self: RenderHandle<Self>, app: &App) -> Option<AlignmentGeometry> {
5138 self.get(app).alignment
5139 }
5140
5141 pub fn set_alignment(
5143 self: RenderHandle<Self>,
5144 app: &mut App,
5145 value: Option<AlignmentGeometry>,
5146 ) {
5147 if self.get(app).alignment == value {
5148 return;
5149 }
5150 self.get_mut(app).alignment = value;
5151 self.mark_needs_paint(app);
5152 }
5153
5154 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
5159 self.get(app).text_direction
5160 }
5161
5162 pub fn set_text_direction(
5164 self: RenderHandle<Self>,
5165 app: &mut App,
5166 value: Option<TextDirection>,
5167 ) {
5168 if self.get(app).text_direction == value {
5169 return;
5170 }
5171 self.get_mut(app).text_direction = value;
5172 self.mark_needs_paint(app);
5173 }
5174
5175 pub fn transform_hit_tests(self: RenderHandle<Self>, app: &App) -> bool {
5183 self.get(app).transform_hit_tests
5184 }
5185
5186 pub fn set_transform_hit_tests(self: RenderHandle<Self>, app: &mut App, value: bool) {
5188 self.get_mut(app).transform_hit_tests = value;
5189 }
5190
5191 pub fn set_transform(self: RenderHandle<Self>, app: &mut App, value: Matrix4) {
5197 if self.get(app).transform == value {
5198 return;
5199 }
5200 self.get_mut(app).transform = value;
5201 self.mark_needs_paint(app);
5202 }
5203
5204 pub fn set_identity(self: RenderHandle<Self>, app: &mut App) {
5206 self.get_mut(app).transform = Matrix4::IDENTITY;
5207 self.mark_needs_paint(app);
5208 }
5209
5210 pub fn rotate_x(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5212 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5213 #[rustfmt::skip]
5214 let rotation = Matrix4::from_flutter_array(&[
5215 1.0, 0.0, 0.0, 0.0,
5216 0.0, cos, sin, 0.0,
5217 0.0, -sin, cos, 0.0,
5218 0.0, 0.0, 0.0, 1.0,
5219 ]);
5220 self.concat(app, &rotation);
5221 }
5222
5223 pub fn rotate_y(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5225 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5226 #[rustfmt::skip]
5227 let rotation = Matrix4::from_flutter_array(&[
5228 cos, 0.0, -sin, 0.0,
5229 0.0, 1.0, 0.0, 0.0,
5230 sin, 0.0, cos, 0.0,
5231 0.0, 0.0, 0.0, 1.0,
5232 ]);
5233 self.concat(app, &rotation);
5234 }
5235
5236 pub fn rotate_z(self: RenderHandle<Self>, app: &mut App, radians: f64) {
5238 let (sin, cos) = (radians.sin() as f32, radians.cos() as f32);
5239 #[rustfmt::skip]
5240 let rotation = Matrix4::from_flutter_array(&[
5241 cos, sin, 0.0, 0.0,
5242 -sin, cos, 0.0, 0.0,
5243 0.0, 0.0, 1.0, 0.0,
5244 0.0, 0.0, 0.0, 1.0,
5245 ]);
5246 self.concat(app, &rotation);
5247 }
5248
5249 pub fn translate(self: RenderHandle<Self>, app: &mut App, x: f64, y: f64, z: f64) {
5251 #[rustfmt::skip]
5252 let translation = Matrix4::from_flutter_array(&[
5253 1.0, 0.0, 0.0, 0.0,
5254 0.0, 1.0, 0.0, 0.0,
5255 0.0, 0.0, 1.0, 0.0,
5256 x as f32, y as f32, z as f32, 1.0,
5257 ]);
5258 self.concat(app, &translation);
5259 }
5260
5261 pub fn scale(self: RenderHandle<Self>, app: &mut App, x: f64, y: Option<f64>, z: Option<f64>) {
5263 let (y, z) = (y.unwrap_or(x) as f32, z.unwrap_or(x) as f32);
5264 #[rustfmt::skip]
5265 let scale = Matrix4::from_flutter_array(&[
5266 x as f32, 0.0, 0.0, 0.0,
5267 0.0, y, 0.0, 0.0,
5268 0.0, 0.0, z, 0.0,
5269 0.0, 0.0, 0.0, 1.0,
5270 ]);
5271 self.concat(app, &scale);
5272 }
5273
5274 fn concat(self: RenderHandle<Self>, app: &mut App, other: &Matrix4) {
5277 crate::object::multiply(&mut self.get_mut(app).transform, other);
5278 self.mark_needs_paint(app);
5279 }
5280
5281 fn effective_transform(self: RenderHandle<Self>, app: &App) -> Matrix4 {
5284 let this = self.get(app);
5285 let resolved_alignment = this
5286 .alignment
5287 .map(|alignment| alignment.resolve(this.text_direction));
5288 let origin = this.origin;
5289 if origin.is_none() && resolved_alignment.is_none() {
5290 return this.transform;
5291 }
5292 let mut result = Matrix4::IDENTITY;
5293 if let Some(origin) = origin {
5294 crate::object::translate(&mut result, origin.dx(), origin.dy());
5295 }
5296 let translation = resolved_alignment.map(|alignment| alignment.along_size(self.size(app)));
5297 if let Some(translation) = translation {
5298 crate::object::translate(&mut result, translation.dx(), translation.dy());
5299 }
5300 crate::object::multiply(&mut result, &self.get(app).transform);
5301 if let Some(translation) = translation {
5302 crate::object::translate(&mut result, -translation.dx(), -translation.dy());
5303 }
5304 if let Some(origin) = origin {
5305 crate::object::translate(&mut result, -origin.dx(), -origin.dy());
5306 }
5307 result
5308 }
5309}
5310
5311impl RenderObjectWithChildMixin for RenderTransform {
5312 type ChildType = AnyRenderBox;
5313
5314 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5315 &self.get(app).child
5316 }
5317
5318 fn child_data_mut(
5319 self: RenderHandle<Self>,
5320 app: &mut App,
5321 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5322 &mut self.get_mut(app).child
5323 }
5324}
5325
5326impl RenderProxyBoxMixin for RenderTransform {}
5327
5328impl RenderObject for RenderTransform {
5329 crate::render_object_accessors!();
5330
5331 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5332 RenderProxyBoxMixin::perform_layout(self, app);
5333 }
5334
5335 fn paint(
5336 self: RenderHandle<Self>,
5337 app: &mut App,
5338 context: &mut PaintingContext,
5339 offset: Offset,
5340 ) {
5341 if self.child(app).is_none() {
5342 return;
5343 }
5344 let transform = self.effective_transform(app);
5345 let Some(child_offset) = get_as_translation(transform) else {
5346 let determinant = transform.determinant();
5349 if determinant == 0.0 || !determinant.is_finite() {
5350 self.as_object().set_layer(app, None);
5351 return;
5352 }
5353 let old = self.as_object().layer_as::<TransformLayer>(app);
5354 let layer = context.push_transform(
5355 app,
5356 self.as_object().needs_compositing(app),
5357 offset,
5358 transform,
5359 |app, context, offset| {
5360 RenderProxyBoxMixin::paint(self, app, context, offset);
5361 },
5362 old,
5363 );
5364 self.as_object()
5365 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5366 return;
5367 };
5368 RenderProxyBoxMixin::paint(self, app, context, offset + child_offset);
5369 self.as_object().set_layer(app, None);
5370 }
5371
5372 fn visit_children(
5373 self: RenderHandle<Self>,
5374 app: &App,
5375 visitor: &mut dyn FnMut(AnyRenderObject),
5376 ) {
5377 if let Some(child) = self.child(app) {
5378 visitor(child.as_object());
5379 }
5380 }
5381}
5382
5383impl RenderBox for RenderTransform {
5384 crate::render_box_accessors!();
5385
5386 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
5387 RenderProxyBoxMixin::setup_parent_data(self, app, child);
5388 }
5389
5390 fn apply_paint_transform(
5391 self: RenderHandle<Self>,
5392 app: &App,
5393 _child: AnyRenderObject,
5394 transform: &mut Matrix4,
5395 ) {
5396 crate::object::multiply(transform, &self.effective_transform(app));
5397 }
5398
5399 fn hit_test(
5400 self: RenderHandle<Self>,
5401 app: &mut App,
5402 result: &mut BoxHitTestResult<'_>,
5403 position: Offset,
5404 ) -> bool {
5405 RenderBox::hit_test_children(self, app, result, position)
5410 }
5411
5412 fn hit_test_children(
5413 self: RenderHandle<Self>,
5414 app: &mut App,
5415 result: &mut BoxHitTestResult<'_>,
5416 position: Offset,
5417 ) -> bool {
5418 let transform = self
5419 .transform_hit_tests(app)
5420 .then(|| self.effective_transform(app));
5421 result.add_with_paint_transform(transform, position, |result, position| {
5422 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5423 })
5424 }
5425
5426 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5427 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5428 }
5429
5430 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5431 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5432 }
5433
5434 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5435 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5436 }
5437
5438 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5439 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5440 }
5441
5442 fn compute_distance_to_actual_baseline(
5443 self: RenderHandle<Self>,
5444 app: &mut App,
5445 baseline: TextBaseline,
5446 ) -> Option<f64> {
5447 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5448 }
5449
5450 fn compute_dry_baseline(
5451 self: RenderHandle<Self>,
5452 app: &mut App,
5453 constraints: BoxConstraints,
5454 baseline: TextBaseline,
5455 ) -> Option<f64> {
5456 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
5457 }
5458
5459 fn compute_dry_layout(
5460 self: RenderHandle<Self>,
5461 app: &mut App,
5462 constraints: BoxConstraints,
5463 ) -> Size {
5464 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
5465 }
5466}
5467
5468pub struct RenderFittedBox {
5470 render_object: RenderObjectData,
5471 render_box: RenderBoxData,
5472 child: RenderObjectWithChildData<AnyRenderBox>,
5473 fit: BoxFit,
5474 alignment: AlignmentGeometry,
5475 text_direction: Option<TextDirection>,
5476 resolved_alignment: Option<Alignment>,
5477 clip_behavior: Clip,
5478 has_visual_overflow: Option<bool>,
5479 transform: Option<Matrix4>,
5480}
5481
5482fn fit_affects_layout(fit: BoxFit) -> bool {
5484 match fit {
5485 BoxFit::ScaleDown => true,
5486 BoxFit::Contain
5487 | BoxFit::Cover
5488 | BoxFit::Fill
5489 | BoxFit::FitHeight
5490 | BoxFit::FitWidth
5491 | BoxFit::None => false,
5492 }
5493}
5494
5495impl RenderFittedBox {
5496 pub fn new(
5498 app: &mut App,
5499 fit: BoxFit,
5500 alignment: AlignmentGeometry,
5501 text_direction: Option<TextDirection>,
5502 child: Option<AnyRenderBox>,
5503 ) -> RenderHandle<RenderFittedBox> {
5504 let this = RenderHandle::new_box(
5505 app,
5506 RenderFittedBox {
5507 render_object: RenderObjectData::new(),
5508 render_box: RenderBoxData::new(),
5509 child: RenderObjectWithChildData::new(),
5510 fit,
5511 alignment,
5512 text_direction,
5513 resolved_alignment: None,
5514 clip_behavior: Clip::None,
5515 has_visual_overflow: None,
5516 transform: None,
5517 },
5518 );
5519 this.set_child(app, child);
5520 this
5521 }
5522
5523 fn resolve(self: RenderHandle<Self>, app: &mut App) -> Alignment {
5524 let this = self.get(app);
5525 if let Some(resolved) = this.resolved_alignment {
5526 return resolved;
5527 }
5528 let resolved = this.alignment.resolve(this.text_direction);
5529 self.get_mut(app).resolved_alignment = Some(resolved);
5530 resolved
5531 }
5532
5533 fn mark_need_resolution(self: RenderHandle<Self>, app: &mut App) {
5534 self.get_mut(app).resolved_alignment = None;
5535 self.mark_needs_paint(app);
5536 }
5537
5538 pub fn fit(self: RenderHandle<Self>, app: &App) -> BoxFit {
5540 self.get(app).fit
5541 }
5542
5543 pub fn set_fit(self: RenderHandle<Self>, app: &mut App, value: BoxFit) {
5545 let last_fit = self.get(app).fit;
5546 if last_fit == value {
5547 return;
5548 }
5549 self.get_mut(app).fit = value;
5550 if fit_affects_layout(last_fit) || fit_affects_layout(value) {
5551 self.mark_needs_layout(app);
5552 } else {
5553 self.clear_paint_data(app);
5554 self.mark_needs_paint(app);
5555 }
5556 }
5557
5558 pub fn alignment(self: RenderHandle<Self>, app: &App) -> AlignmentGeometry {
5564 self.get(app).alignment
5565 }
5566
5567 pub fn set_alignment(self: RenderHandle<Self>, app: &mut App, value: AlignmentGeometry) {
5569 if self.get(app).alignment == value {
5570 return;
5571 }
5572 self.get_mut(app).alignment = value;
5573 self.clear_paint_data(app);
5574 self.mark_need_resolution(app);
5575 }
5576
5577 pub fn text_direction(self: RenderHandle<Self>, app: &App) -> Option<TextDirection> {
5579 self.get(app).text_direction
5580 }
5581
5582 pub fn set_text_direction(
5584 self: RenderHandle<Self>,
5585 app: &mut App,
5586 value: Option<TextDirection>,
5587 ) {
5588 if self.get(app).text_direction == value {
5589 return;
5590 }
5591 self.get_mut(app).text_direction = value;
5592 self.clear_paint_data(app);
5593 self.mark_need_resolution(app);
5594 }
5595
5596 pub fn clip_behavior(self: RenderHandle<Self>, app: &App) -> Clip {
5598 self.get(app).clip_behavior
5599 }
5600
5601 pub fn set_clip_behavior(self: RenderHandle<Self>, app: &mut App, value: Clip) {
5603 if self.get(app).clip_behavior == value {
5604 return;
5605 }
5606 self.get_mut(app).clip_behavior = value;
5607 self.mark_needs_paint(app);
5608 }
5609
5610 pub fn paints_child(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> bool {
5615 debug_assert_eq!(child.as_object().parent(app), Some(self.as_object()));
5616 !self.size(app).is_empty() && !child.size(app).is_empty()
5617 }
5618
5619 fn clear_paint_data(self: RenderHandle<Self>, app: &mut App) {
5620 let this = self.get_mut(app);
5621 this.has_visual_overflow = None;
5622 this.transform = None;
5623 }
5624
5625 fn paint_data(self: RenderHandle<Self>, app: &App) -> (bool, Matrix4) {
5628 let Some(child) = self.child(app) else {
5629 return (false, Matrix4::IDENTITY);
5630 };
5631 let this = self.get(app);
5632 let resolved_alignment = this
5633 .resolved_alignment
5634 .unwrap_or_else(|| this.alignment.resolve(this.text_direction));
5635 let child_size = child.size(app);
5636 let sizes = apply_box_fit(this.fit, child_size, self.size(app));
5637 let scale_x = sizes.destination.width() / sizes.source.width();
5638 let scale_y = sizes.destination.height() / sizes.source.height();
5639 let source_rect = resolved_alignment.inscribe(sizes.source, Offset::ZERO & child_size);
5640 let destination_rect =
5641 resolved_alignment.inscribe(sizes.destination, Offset::ZERO & self.size(app));
5642 debug_assert!(scale_x.is_finite() && scale_y.is_finite());
5643 let mut transform =
5644 Matrix4::translation(destination_rect.left as f32, destination_rect.top as f32);
5645 crate::object::multiply(
5646 &mut transform,
5647 &Matrix4::scale(scale_x as f32, scale_y as f32),
5648 );
5649 crate::object::translate(&mut transform, -source_rect.left, -source_rect.top);
5650 let has_visual_overflow =
5651 source_rect.width() < child_size.width() || source_rect.height() < child_size.height();
5652 (has_visual_overflow, transform)
5653 }
5654
5655 fn update_paint_data(self: RenderHandle<Self>, app: &mut App) {
5656 if self.get(app).transform.is_some() {
5657 return;
5658 }
5659 self.resolve(app);
5661 let (has_visual_overflow, transform) = self.paint_data(app);
5662 let this = self.get_mut(app);
5663 this.has_visual_overflow = Some(has_visual_overflow);
5664 this.transform = Some(transform);
5665 }
5666
5667 fn paint_child_with_transform(
5668 self: RenderHandle<Self>,
5669 app: &mut App,
5670 context: &mut PaintingContext,
5671 offset: Offset,
5672 ) -> Option<Handle<TransformLayer>> {
5673 let transform = self.get(app).transform.expect("update_paint_data ran");
5674 match get_as_translation(transform) {
5675 Some(child_offset) => {
5676 RenderProxyBoxMixin::paint(self, app, context, offset + child_offset);
5677 None
5678 }
5679 None => context.push_transform(
5680 app,
5681 self.as_object().needs_compositing(app),
5682 offset,
5683 transform,
5684 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
5685 self.as_object().layer_as::<TransformLayer>(app),
5686 ),
5687 }
5688 }
5689}
5690
5691impl RenderObjectWithChildMixin for RenderFittedBox {
5692 type ChildType = AnyRenderBox;
5693
5694 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5695 &self.get(app).child
5696 }
5697
5698 fn child_data_mut(
5699 self: RenderHandle<Self>,
5700 app: &mut App,
5701 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5702 &mut self.get_mut(app).child
5703 }
5704}
5705
5706impl RenderProxyBoxMixin for RenderFittedBox {}
5707
5708impl RenderObject for RenderFittedBox {
5709 crate::render_object_accessors!();
5710
5711 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5712 let constraints = self.constraints(app);
5713 let Some(child) = self.child(app) else {
5714 self.set_size(app, constraints.smallest());
5715 return;
5716 };
5717 child.layout(app, BoxConstraints::new(), true);
5718 let child_size = child.size(app);
5719 let size = match self.fit(app) {
5720 BoxFit::ScaleDown => {
5721 let size_constraints = constraints.loosen();
5722 let unconstrained_size = size_constraints
5723 .constrain_size_and_attempt_to_preserve_aspect_ratio(child_size);
5724 constraints.constrain(unconstrained_size)
5725 }
5726 BoxFit::Contain
5727 | BoxFit::Cover
5728 | BoxFit::Fill
5729 | BoxFit::FitHeight
5730 | BoxFit::FitWidth
5731 | BoxFit::None => {
5732 constraints.constrain_size_and_attempt_to_preserve_aspect_ratio(child_size)
5733 }
5734 };
5735 self.set_size(app, size);
5736 self.clear_paint_data(app);
5737 }
5738
5739 fn paint(
5740 self: RenderHandle<Self>,
5741 app: &mut App,
5742 context: &mut PaintingContext,
5743 offset: Offset,
5744 ) {
5745 let Some(child) = self.child(app) else {
5746 return;
5747 };
5748 if self.size(app).is_empty() || child.size(app).is_empty() {
5749 return;
5750 }
5751 self.update_paint_data(app);
5752 let clip_behavior = self.clip_behavior(app);
5753 if self.get(app).has_visual_overflow == Some(true) && clip_behavior != Clip::None {
5754 let clip_rect = Offset::ZERO & self.size(app);
5755 let old = self.as_object().layer_as::<ClipRectLayer>(app);
5756 let layer = context.push_clip_rect(
5757 app,
5758 self.as_object().needs_compositing(app),
5759 offset,
5760 clip_rect,
5761 |app, context, offset| {
5762 let _ = self.paint_child_with_transform(app, context, offset);
5763 },
5764 clip_behavior,
5765 old,
5766 );
5767 self.as_object()
5768 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5769 } else {
5770 let layer = self.paint_child_with_transform(app, context, offset);
5771 self.as_object()
5772 .set_layer(app, layer.map(|layer| layer.as_container_layer()));
5773 }
5774 }
5775
5776 fn visit_children(
5777 self: RenderHandle<Self>,
5778 app: &App,
5779 visitor: &mut dyn FnMut(AnyRenderObject),
5780 ) {
5781 if let Some(child) = self.child(app) {
5782 visitor(child.as_object());
5783 }
5784 }
5785}
5786
5787impl RenderBox for RenderFittedBox {
5788 crate::render_box_accessors!();
5789
5790 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
5791 RenderProxyBoxMixin::setup_parent_data(self, app, child);
5792 }
5793
5794 fn apply_paint_transform(
5795 self: RenderHandle<Self>,
5796 app: &App,
5797 child: AnyRenderObject,
5798 transform: &mut Matrix4,
5799 ) {
5800 let child = child.as_box().expect("a fitted box has a box child");
5801 if !self.paints_child(app, child) {
5802 *transform = crate::object::zero_matrix();
5803 return;
5804 }
5805 let (_, fitted) = self.paint_data(app);
5806 crate::object::multiply(transform, &fitted);
5807 }
5808
5809 fn hit_test_children(
5810 self: RenderHandle<Self>,
5811 app: &mut App,
5812 result: &mut BoxHitTestResult<'_>,
5813 position: Offset,
5814 ) -> bool {
5815 let child_is_empty = self
5816 .child(app)
5817 .is_none_or(|child| child.size(app).is_empty());
5818 if self.size(app).is_empty() || child_is_empty {
5819 return false;
5820 }
5821 self.update_paint_data(app);
5822 let transform = self.get(app).transform;
5823 result.add_with_paint_transform(transform, position, |result, position| {
5824 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
5825 })
5826 }
5827
5828 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5829 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
5830 }
5831
5832 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
5833 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
5834 }
5835
5836 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5837 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
5838 }
5839
5840 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
5841 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
5842 }
5843
5844 fn compute_distance_to_actual_baseline(
5845 self: RenderHandle<Self>,
5846 app: &mut App,
5847 baseline: TextBaseline,
5848 ) -> Option<f64> {
5849 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
5850 }
5851
5852 fn compute_dry_layout(
5853 self: RenderHandle<Self>,
5854 app: &mut App,
5855 constraints: BoxConstraints,
5856 ) -> Size {
5857 let Some(child) = self.child(app) else {
5858 return constraints.smallest();
5859 };
5860 let child_size = child.get_dry_layout(app, BoxConstraints::new());
5861 match self.fit(app) {
5862 BoxFit::ScaleDown => {
5863 let size_constraints = constraints.loosen();
5864 let unconstrained_size = size_constraints
5865 .constrain_size_and_attempt_to_preserve_aspect_ratio(child_size);
5866 constraints.constrain(unconstrained_size)
5867 }
5868 BoxFit::Contain
5869 | BoxFit::Cover
5870 | BoxFit::Fill
5871 | BoxFit::FitHeight
5872 | BoxFit::FitWidth
5873 | BoxFit::None => {
5874 constraints.constrain_size_and_attempt_to_preserve_aspect_ratio(child_size)
5875 }
5876 }
5877 }
5878
5879 fn compute_dry_baseline(
5880 self: RenderHandle<Self>,
5881 app: &mut App,
5882 _constraints: BoxConstraints,
5883 baseline: TextBaseline,
5884 ) -> Option<f64> {
5885 self.child(app)?
5888 .get_dry_baseline(app, BoxConstraints::new(), baseline)
5889 }
5890}
5891
5892pub struct RenderFractionalTranslation {
5902 render_object: RenderObjectData,
5903 render_box: RenderBoxData,
5904 child: RenderObjectWithChildData<AnyRenderBox>,
5905 translation: Offset,
5906 transform_hit_tests: bool,
5907}
5908
5909impl RenderFractionalTranslation {
5910 pub fn new(
5912 app: &mut App,
5913 translation: Offset,
5914 transform_hit_tests: bool,
5915 child: Option<AnyRenderBox>,
5916 ) -> RenderHandle<RenderFractionalTranslation> {
5917 let this = RenderHandle::new_box(
5918 app,
5919 RenderFractionalTranslation {
5920 render_object: RenderObjectData::new(),
5921 render_box: RenderBoxData::new(),
5922 child: RenderObjectWithChildData::new(),
5923 translation,
5924 transform_hit_tests,
5925 },
5926 );
5927 this.set_child(app, child);
5928 this
5929 }
5930
5931 pub fn translation(self: RenderHandle<Self>, app: &App) -> Offset {
5936 self.get(app).translation
5937 }
5938
5939 pub fn set_translation(self: RenderHandle<Self>, app: &mut App, value: Offset) {
5941 if self.get(app).translation == value {
5942 return;
5943 }
5944 self.get_mut(app).translation = value;
5945 self.mark_needs_paint(app);
5946 }
5947
5948 pub fn transform_hit_tests(self: RenderHandle<Self>, app: &App) -> bool {
5956 self.get(app).transform_hit_tests
5957 }
5958
5959 pub fn set_transform_hit_tests(self: RenderHandle<Self>, app: &mut App, value: bool) {
5961 self.get_mut(app).transform_hit_tests = value;
5962 }
5963
5964 fn absolute_translation(self: RenderHandle<Self>, app: &App) -> Offset {
5966 let translation = self.get(app).translation;
5967 let size = self.size(app);
5968 Offset::new(
5969 translation.dx() * size.width(),
5970 translation.dy() * size.height(),
5971 )
5972 }
5973}
5974
5975impl RenderObjectWithChildMixin for RenderFractionalTranslation {
5976 type ChildType = AnyRenderBox;
5977
5978 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
5979 &self.get(app).child
5980 }
5981
5982 fn child_data_mut(
5983 self: RenderHandle<Self>,
5984 app: &mut App,
5985 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
5986 &mut self.get_mut(app).child
5987 }
5988}
5989
5990impl RenderProxyBoxMixin for RenderFractionalTranslation {}
5991
5992impl RenderObject for RenderFractionalTranslation {
5993 crate::render_object_accessors!();
5994
5995 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
5996 RenderProxyBoxMixin::perform_layout(self, app);
5997 }
5998
5999 fn paint(
6000 self: RenderHandle<Self>,
6001 app: &mut App,
6002 context: &mut PaintingContext,
6003 offset: Offset,
6004 ) {
6005 debug_assert!(!self.debug_needs_layout(app));
6006 if self.child(app).is_none() {
6007 return;
6008 }
6009 let translation = self.absolute_translation(app);
6010 RenderProxyBoxMixin::paint(self, app, context, offset + translation);
6011 }
6012
6013 fn visit_children(
6014 self: RenderHandle<Self>,
6015 app: &App,
6016 visitor: &mut dyn FnMut(AnyRenderObject),
6017 ) {
6018 if let Some(child) = self.child(app) {
6019 visitor(child.as_object());
6020 }
6021 }
6022}
6023
6024impl RenderBox for RenderFractionalTranslation {
6025 crate::render_box_accessors!();
6026
6027 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6028 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6029 }
6030
6031 fn apply_paint_transform(
6032 self: RenderHandle<Self>,
6033 app: &App,
6034 _child: AnyRenderObject,
6035 transform: &mut Matrix4,
6036 ) {
6037 let translation = self.absolute_translation(app);
6038 crate::object::translate(transform, translation.dx(), translation.dy());
6039 }
6040
6041 fn hit_test(
6042 self: RenderHandle<Self>,
6043 app: &mut App,
6044 result: &mut BoxHitTestResult<'_>,
6045 position: Offset,
6046 ) -> bool {
6047 RenderBox::hit_test_children(self, app, result, position)
6052 }
6053
6054 fn hit_test_children(
6055 self: RenderHandle<Self>,
6056 app: &mut App,
6057 result: &mut BoxHitTestResult<'_>,
6058 position: Offset,
6059 ) -> bool {
6060 debug_assert!(!self.debug_needs_layout(app));
6061 let offset = self
6062 .transform_hit_tests(app)
6063 .then(|| self.absolute_translation(app));
6064 result.add_with_paint_offset(offset, position, |result, position| {
6065 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6066 })
6067 }
6068
6069 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6070 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6071 }
6072
6073 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6074 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6075 }
6076
6077 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6078 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6079 }
6080
6081 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6082 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6083 }
6084
6085 fn compute_distance_to_actual_baseline(
6086 self: RenderHandle<Self>,
6087 app: &mut App,
6088 baseline: TextBaseline,
6089 ) -> Option<f64> {
6090 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6091 }
6092
6093 fn compute_dry_baseline(
6094 self: RenderHandle<Self>,
6095 app: &mut App,
6096 constraints: BoxConstraints,
6097 baseline: TextBaseline,
6098 ) -> Option<f64> {
6099 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6100 }
6101
6102 fn compute_dry_layout(
6103 self: RenderHandle<Self>,
6104 app: &mut App,
6105 constraints: BoxConstraints,
6106 ) -> Size {
6107 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6108 }
6109}
6110
6111pub struct RenderIgnorePointer {
6123 render_object: RenderObjectData,
6124 render_box: RenderBoxData,
6125 child: RenderObjectWithChildData<AnyRenderBox>,
6126 ignoring: bool,
6127}
6128
6129impl RenderIgnorePointer {
6130 pub fn new(
6132 app: &mut App,
6133 ignoring: bool,
6134 child: Option<AnyRenderBox>,
6135 ) -> RenderHandle<RenderIgnorePointer> {
6136 let this = RenderHandle::new_box(
6137 app,
6138 RenderIgnorePointer {
6139 render_object: RenderObjectData::new(),
6140 render_box: RenderBoxData::new(),
6141 child: RenderObjectWithChildData::new(),
6142 ignoring,
6143 },
6144 );
6145 this.set_child(app, child);
6146 this
6147 }
6148
6149 pub fn ignoring(self: RenderHandle<Self>, app: &App) -> bool {
6154 self.get(app).ignoring
6155 }
6156
6157 pub fn set_ignoring(self: RenderHandle<Self>, app: &mut App, value: bool) {
6159 if value == self.get(app).ignoring {
6160 return;
6161 }
6162 self.get_mut(app).ignoring = value;
6163 }
6164}
6165
6166impl RenderObjectWithChildMixin for RenderIgnorePointer {
6167 type ChildType = AnyRenderBox;
6168
6169 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6170 &self.get(app).child
6171 }
6172
6173 fn child_data_mut(
6174 self: RenderHandle<Self>,
6175 app: &mut App,
6176 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6177 &mut self.get_mut(app).child
6178 }
6179}
6180
6181impl RenderProxyBoxMixin for RenderIgnorePointer {}
6182
6183impl RenderObject for RenderIgnorePointer {
6184 crate::render_object_accessors!();
6185
6186 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6187 RenderProxyBoxMixin::perform_layout(self, app);
6188 }
6189
6190 fn paint(
6191 self: RenderHandle<Self>,
6192 app: &mut App,
6193 context: &mut PaintingContext,
6194 offset: Offset,
6195 ) {
6196 RenderProxyBoxMixin::paint(self, app, context, offset);
6197 }
6198
6199 fn visit_children(
6200 self: RenderHandle<Self>,
6201 app: &App,
6202 visitor: &mut dyn FnMut(AnyRenderObject),
6203 ) {
6204 if let Some(child) = self.child(app) {
6205 visitor(child.as_object());
6206 }
6207 }
6208}
6209
6210impl RenderBox for RenderIgnorePointer {
6211 crate::render_box_accessors!();
6212
6213 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6214 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6215 }
6216
6217 fn apply_paint_transform(
6218 self: RenderHandle<Self>,
6219 app: &App,
6220 child: AnyRenderObject,
6221 transform: &mut Matrix4,
6222 ) {
6223 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6224 }
6225
6226 fn hit_test(
6227 self: RenderHandle<Self>,
6228 app: &mut App,
6229 result: &mut BoxHitTestResult<'_>,
6230 position: Offset,
6231 ) -> bool {
6232 !self.ignoring(app) && RenderBoxBase::hit_test(self, app, result, position)
6233 }
6234
6235 fn hit_test_children(
6236 self: RenderHandle<Self>,
6237 app: &mut App,
6238 result: &mut BoxHitTestResult<'_>,
6239 position: Offset,
6240 ) -> bool {
6241 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6242 }
6243
6244 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6245 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6246 }
6247
6248 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6249 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6250 }
6251
6252 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6253 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6254 }
6255
6256 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6257 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6258 }
6259
6260 fn compute_distance_to_actual_baseline(
6261 self: RenderHandle<Self>,
6262 app: &mut App,
6263 baseline: TextBaseline,
6264 ) -> Option<f64> {
6265 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6266 }
6267
6268 fn compute_dry_baseline(
6269 self: RenderHandle<Self>,
6270 app: &mut App,
6271 constraints: BoxConstraints,
6272 baseline: TextBaseline,
6273 ) -> Option<f64> {
6274 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6275 }
6276
6277 fn compute_dry_layout(
6278 self: RenderHandle<Self>,
6279 app: &mut App,
6280 constraints: BoxConstraints,
6281 ) -> Size {
6282 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6283 }
6284}
6285
6286pub struct RenderOffstage {
6290 render_object: RenderObjectData,
6291 render_box: RenderBoxData,
6292 child: RenderObjectWithChildData<AnyRenderBox>,
6293 offstage: bool,
6294}
6295
6296impl RenderOffstage {
6297 pub fn new(
6299 app: &mut App,
6300 offstage: bool,
6301 child: Option<AnyRenderBox>,
6302 ) -> RenderHandle<RenderOffstage> {
6303 let this = RenderHandle::new_box(
6304 app,
6305 RenderOffstage {
6306 render_object: RenderObjectData::new(),
6307 render_box: RenderBoxData::new(),
6308 child: RenderObjectWithChildData::new(),
6309 offstage,
6310 },
6311 );
6312 this.set_child(app, child);
6313 this
6314 }
6315
6316 pub fn offstage(self: RenderHandle<Self>, app: &App) -> bool {
6324 self.get(app).offstage
6325 }
6326
6327 pub fn set_offstage(self: RenderHandle<Self>, app: &mut App, value: bool) {
6329 if value == self.get(app).offstage {
6330 return;
6331 }
6332 self.get_mut(app).offstage = value;
6333 self.as_object()
6334 .mark_needs_layout_for_sized_by_parent_change(app);
6335 }
6336
6337 pub fn paints_child(self: RenderHandle<Self>, app: &App, child: AnyRenderBox) -> bool {
6342 debug_assert_eq!(child.as_object().parent(app), Some(self.as_object()));
6343 !self.get(app).offstage
6344 }
6345}
6346
6347impl RenderObjectWithChildMixin for RenderOffstage {
6348 type ChildType = AnyRenderBox;
6349
6350 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6351 &self.get(app).child
6352 }
6353
6354 fn child_data_mut(
6355 self: RenderHandle<Self>,
6356 app: &mut App,
6357 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6358 &mut self.get_mut(app).child
6359 }
6360}
6361
6362impl RenderProxyBoxMixin for RenderOffstage {}
6363
6364impl RenderObject for RenderOffstage {
6365 crate::render_object_accessors!();
6366
6367 fn sized_by_parent(self: RenderHandle<Self>, app: &App) -> bool {
6368 self.get(app).offstage
6369 }
6370
6371 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6372 if !self.get(app).offstage {
6373 RenderProxyBoxMixin::perform_layout(self, app);
6374 return;
6375 }
6376 if let Some(child) = self.child(app) {
6377 let constraints = self.constraints(app);
6378 child.layout(app, constraints, false);
6379 }
6380 }
6381
6382 fn paint(
6383 self: RenderHandle<Self>,
6384 app: &mut App,
6385 context: &mut PaintingContext,
6386 offset: Offset,
6387 ) {
6388 if self.get(app).offstage {
6389 return;
6390 }
6391 RenderProxyBoxMixin::paint(self, app, context, offset);
6392 }
6393
6394 fn visit_children(
6395 self: RenderHandle<Self>,
6396 app: &App,
6397 visitor: &mut dyn FnMut(AnyRenderObject),
6398 ) {
6399 if let Some(child) = self.child(app) {
6400 visitor(child.as_object());
6401 }
6402 }
6403}
6404
6405impl RenderBox for RenderOffstage {
6406 crate::render_box_accessors!();
6407
6408 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6409 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6410 }
6411
6412 fn apply_paint_transform(
6413 self: RenderHandle<Self>,
6414 app: &App,
6415 child: AnyRenderObject,
6416 transform: &mut Matrix4,
6417 ) {
6418 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6419 }
6420
6421 fn hit_test(
6422 self: RenderHandle<Self>,
6423 app: &mut App,
6424 result: &mut BoxHitTestResult<'_>,
6425 position: Offset,
6426 ) -> bool {
6427 !self.get(app).offstage && RenderBoxBase::hit_test(self, app, result, position)
6428 }
6429
6430 fn hit_test_children(
6431 self: RenderHandle<Self>,
6432 app: &mut App,
6433 result: &mut BoxHitTestResult<'_>,
6434 position: Offset,
6435 ) -> bool {
6436 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6437 }
6438
6439 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6440 if self.get(app).offstage {
6441 return 0.0;
6442 }
6443 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6444 }
6445
6446 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6447 if self.get(app).offstage {
6448 return 0.0;
6449 }
6450 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6451 }
6452
6453 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6454 if self.get(app).offstage {
6455 return 0.0;
6456 }
6457 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6458 }
6459
6460 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6461 if self.get(app).offstage {
6462 return 0.0;
6463 }
6464 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6465 }
6466
6467 fn compute_distance_to_actual_baseline(
6468 self: RenderHandle<Self>,
6469 app: &mut App,
6470 baseline: TextBaseline,
6471 ) -> Option<f64> {
6472 if self.get(app).offstage {
6473 return None;
6474 }
6475 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6476 }
6477
6478 fn compute_dry_baseline(
6479 self: RenderHandle<Self>,
6480 app: &mut App,
6481 constraints: BoxConstraints,
6482 baseline: TextBaseline,
6483 ) -> Option<f64> {
6484 if self.get(app).offstage {
6485 return None;
6486 }
6487 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6488 }
6489
6490 fn compute_dry_layout(
6491 self: RenderHandle<Self>,
6492 app: &mut App,
6493 constraints: BoxConstraints,
6494 ) -> Size {
6495 if self.get(app).offstage {
6496 return constraints.smallest();
6497 }
6498 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6499 }
6500
6501 fn perform_resize(self: RenderHandle<Self>, app: &mut App) {
6503 debug_assert!(self.get(app).offstage);
6504 RenderBoxBase::perform_resize(self, app);
6505 }
6506}
6507
6508pub struct RenderAbsorbPointer {
6521 render_object: RenderObjectData,
6522 render_box: RenderBoxData,
6523 child: RenderObjectWithChildData<AnyRenderBox>,
6524 absorbing: bool,
6525}
6526
6527impl RenderAbsorbPointer {
6528 pub fn new(
6530 app: &mut App,
6531 absorbing: bool,
6532 child: Option<AnyRenderBox>,
6533 ) -> RenderHandle<RenderAbsorbPointer> {
6534 let this = RenderHandle::new_box(
6535 app,
6536 RenderAbsorbPointer {
6537 render_object: RenderObjectData::new(),
6538 render_box: RenderBoxData::new(),
6539 child: RenderObjectWithChildData::new(),
6540 absorbing,
6541 },
6542 );
6543 this.set_child(app, child);
6544 this
6545 }
6546
6547 pub fn absorbing(self: RenderHandle<Self>, app: &App) -> bool {
6553 self.get(app).absorbing
6554 }
6555
6556 pub fn set_absorbing(self: RenderHandle<Self>, app: &mut App, value: bool) {
6558 if self.get(app).absorbing == value {
6559 return;
6560 }
6561 self.get_mut(app).absorbing = value;
6562 }
6563}
6564
6565impl RenderObjectWithChildMixin for RenderAbsorbPointer {
6566 type ChildType = AnyRenderBox;
6567
6568 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6569 &self.get(app).child
6570 }
6571
6572 fn child_data_mut(
6573 self: RenderHandle<Self>,
6574 app: &mut App,
6575 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6576 &mut self.get_mut(app).child
6577 }
6578}
6579
6580impl RenderProxyBoxMixin for RenderAbsorbPointer {}
6581
6582impl RenderObject for RenderAbsorbPointer {
6583 crate::render_object_accessors!();
6584
6585 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6586 RenderProxyBoxMixin::perform_layout(self, app);
6587 }
6588
6589 fn paint(
6590 self: RenderHandle<Self>,
6591 app: &mut App,
6592 context: &mut PaintingContext,
6593 offset: Offset,
6594 ) {
6595 RenderProxyBoxMixin::paint(self, app, context, offset);
6596 }
6597
6598 fn visit_children(
6599 self: RenderHandle<Self>,
6600 app: &App,
6601 visitor: &mut dyn FnMut(AnyRenderObject),
6602 ) {
6603 if let Some(child) = self.child(app) {
6604 visitor(child.as_object());
6605 }
6606 }
6607}
6608
6609impl RenderBox for RenderAbsorbPointer {
6610 crate::render_box_accessors!();
6611
6612 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6613 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6614 }
6615
6616 fn apply_paint_transform(
6617 self: RenderHandle<Self>,
6618 app: &App,
6619 child: AnyRenderObject,
6620 transform: &mut Matrix4,
6621 ) {
6622 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6623 }
6624
6625 fn hit_test(
6626 self: RenderHandle<Self>,
6627 app: &mut App,
6628 result: &mut BoxHitTestResult<'_>,
6629 position: Offset,
6630 ) -> bool {
6631 if self.absorbing(app) {
6632 return self.size(app).contains(position);
6633 }
6634 RenderBoxBase::hit_test(self, app, result, position)
6635 }
6636
6637 fn hit_test_children(
6638 self: RenderHandle<Self>,
6639 app: &mut App,
6640 result: &mut BoxHitTestResult<'_>,
6641 position: Offset,
6642 ) -> bool {
6643 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6644 }
6645
6646 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6647 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6648 }
6649
6650 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6651 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6652 }
6653
6654 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6655 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6656 }
6657
6658 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6659 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6660 }
6661
6662 fn compute_distance_to_actual_baseline(
6663 self: RenderHandle<Self>,
6664 app: &mut App,
6665 baseline: TextBaseline,
6666 ) -> Option<f64> {
6667 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6668 }
6669
6670 fn compute_dry_baseline(
6671 self: RenderHandle<Self>,
6672 app: &mut App,
6673 constraints: BoxConstraints,
6674 baseline: TextBaseline,
6675 ) -> Option<f64> {
6676 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6677 }
6678
6679 fn compute_dry_layout(
6680 self: RenderHandle<Self>,
6681 app: &mut App,
6682 constraints: BoxConstraints,
6683 ) -> Size {
6684 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6685 }
6686}
6687
6688pub struct RenderColoredBox {
6693 render_object: RenderObjectData,
6694 render_box: RenderBoxData,
6695 child: RenderObjectWithChildData<AnyRenderBox>,
6696 color: Color,
6697 is_anti_alias: bool,
6698 behavior: HitTestBehavior,
6699}
6700
6701impl RenderColoredBox {
6702 pub fn new(
6704 app: &mut App,
6705 color: Color,
6706 is_anti_alias: bool,
6707 child: Option<AnyRenderBox>,
6708 ) -> RenderHandle<RenderColoredBox> {
6709 let this = RenderHandle::new_box(
6710 app,
6711 RenderColoredBox {
6712 render_object: RenderObjectData::new(),
6713 render_box: RenderBoxData::new(),
6714 child: RenderObjectWithChildData::new(),
6715 color,
6716 is_anti_alias,
6717 behavior: HitTestBehavior::Opaque,
6718 },
6719 );
6720 this.set_child(app, child);
6721 this
6722 }
6723
6724 pub fn color(self: RenderHandle<Self>, app: &App) -> Color {
6726 self.get(app).color
6727 }
6728
6729 pub fn set_color(self: RenderHandle<Self>, app: &mut App, value: Color) {
6731 if value == self.get(app).color {
6732 return;
6733 }
6734 self.get_mut(app).color = value;
6735 self.mark_needs_paint(app);
6736 }
6737
6738 pub fn is_anti_alias(self: RenderHandle<Self>, app: &App) -> bool {
6740 self.get(app).is_anti_alias
6741 }
6742
6743 pub fn set_is_anti_alias(self: RenderHandle<Self>, app: &mut App, value: bool) {
6745 if value == self.get(app).is_anti_alias {
6746 return;
6747 }
6748 self.get_mut(app).is_anti_alias = value;
6749 self.mark_needs_paint(app);
6750 }
6751}
6752
6753impl RenderObjectWithChildMixin for RenderColoredBox {
6754 type ChildType = AnyRenderBox;
6755
6756 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6757 &self.get(app).child
6758 }
6759
6760 fn child_data_mut(
6761 self: RenderHandle<Self>,
6762 app: &mut App,
6763 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6764 &mut self.get_mut(app).child
6765 }
6766}
6767
6768impl RenderProxyBoxMixin for RenderColoredBox {}
6769
6770impl RenderProxyBoxWithHitTestBehavior for RenderColoredBox {
6771 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
6772 self.get(app).behavior
6773 }
6774}
6775
6776impl RenderObject for RenderColoredBox {
6777 crate::render_object_accessors!();
6778
6779 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6780 RenderProxyBoxMixin::perform_layout(self, app);
6781 }
6782
6783 fn paint(
6784 self: RenderHandle<Self>,
6785 app: &mut App,
6786 context: &mut PaintingContext,
6787 offset: Offset,
6788 ) {
6789 let size = self.size(app);
6794 if size.gt(&Size::ZERO) {
6795 let paint = Paint {
6796 color: self.get(app).color.into(),
6797 ..Paint::default()
6798 };
6799 context.canvas().draw_rect(offset & size, &paint);
6800 }
6801 if let Some(child) = self.child(app) {
6802 context.paint_child(app, child.as_object(), offset);
6803 }
6804 }
6805
6806 fn visit_children(
6807 self: RenderHandle<Self>,
6808 app: &App,
6809 visitor: &mut dyn FnMut(AnyRenderObject),
6810 ) {
6811 if let Some(child) = self.child(app) {
6812 visitor(child.as_object());
6813 }
6814 }
6815}
6816
6817impl RenderBox for RenderColoredBox {
6818 crate::render_box_accessors!();
6819
6820 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
6821 RenderProxyBoxMixin::setup_parent_data(self, app, child);
6822 }
6823
6824 fn apply_paint_transform(
6825 self: RenderHandle<Self>,
6826 app: &App,
6827 child: AnyRenderObject,
6828 transform: &mut Matrix4,
6829 ) {
6830 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
6831 }
6832
6833 fn hit_test(
6834 self: RenderHandle<Self>,
6835 app: &mut App,
6836 result: &mut BoxHitTestResult<'_>,
6837 position: Offset,
6838 ) -> bool {
6839 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
6840 }
6841
6842 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
6843 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
6844 }
6845
6846 fn hit_test_children(
6847 self: RenderHandle<Self>,
6848 app: &mut App,
6849 result: &mut BoxHitTestResult<'_>,
6850 position: Offset,
6851 ) -> bool {
6852 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
6853 }
6854
6855 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6856 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
6857 }
6858
6859 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
6860 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
6861 }
6862
6863 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6864 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
6865 }
6866
6867 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
6868 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
6869 }
6870
6871 fn compute_distance_to_actual_baseline(
6872 self: RenderHandle<Self>,
6873 app: &mut App,
6874 baseline: TextBaseline,
6875 ) -> Option<f64> {
6876 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
6877 }
6878
6879 fn compute_dry_baseline(
6880 self: RenderHandle<Self>,
6881 app: &mut App,
6882 constraints: BoxConstraints,
6883 baseline: TextBaseline,
6884 ) -> Option<f64> {
6885 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
6886 }
6887
6888 fn compute_dry_layout(
6889 self: RenderHandle<Self>,
6890 app: &mut App,
6891 constraints: BoxConstraints,
6892 ) -> Size {
6893 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
6894 }
6895}
6896
6897pub struct RenderMetaData {
6904 render_object: RenderObjectData,
6905 render_box: RenderBoxData,
6906 child: RenderObjectWithChildData<AnyRenderBox>,
6907 meta_data: Option<Rc<dyn Any>>,
6908 behavior: HitTestBehavior,
6909}
6910
6911impl RenderMetaData {
6912 pub fn new(
6916 app: &mut App,
6917 meta_data: Option<Rc<dyn Any>>,
6918 behavior: HitTestBehavior,
6919 child: Option<AnyRenderBox>,
6920 ) -> RenderHandle<Self> {
6921 let this = RenderHandle::new_box(
6922 app,
6923 RenderMetaData {
6924 render_object: RenderObjectData::new(),
6925 render_box: RenderBoxData::new(),
6926 child: RenderObjectWithChildData::new(),
6927 meta_data,
6928 behavior,
6929 },
6930 );
6931 this.set_child(app, child);
6932 this
6933 }
6934
6935 pub fn meta_data(self: RenderHandle<Self>, app: &App) -> Option<Rc<dyn Any>> {
6937 self.get(app).meta_data.clone()
6938 }
6939
6940 pub fn set_meta_data(self: RenderHandle<Self>, app: &mut App, value: Option<Rc<dyn Any>>) {
6942 self.get_mut(app).meta_data = value;
6943 }
6944
6945 pub fn set_behavior(self: RenderHandle<Self>, app: &mut App, value: HitTestBehavior) {
6947 self.get_mut(app).behavior = value;
6948 }
6949}
6950
6951impl RenderObjectWithChildMixin for RenderMetaData {
6952 type ChildType = AnyRenderBox;
6953
6954 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
6955 &self.get(app).child
6956 }
6957
6958 fn child_data_mut(
6959 self: RenderHandle<Self>,
6960 app: &mut App,
6961 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
6962 &mut self.get_mut(app).child
6963 }
6964}
6965
6966impl RenderProxyBoxMixin for RenderMetaData {}
6967
6968impl RenderProxyBoxWithHitTestBehavior for RenderMetaData {
6969 fn behavior(self: RenderHandle<Self>, app: &App) -> HitTestBehavior {
6970 self.get(app).behavior
6971 }
6972}
6973
6974impl RenderObject for RenderMetaData {
6975 crate::render_object_accessors!();
6976
6977 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
6978 RenderProxyBoxMixin::perform_layout(self, app);
6979 }
6980
6981 fn paint(
6982 self: RenderHandle<Self>,
6983 app: &mut App,
6984 context: &mut PaintingContext,
6985 offset: Offset,
6986 ) {
6987 RenderProxyBoxMixin::paint(self, app, context, offset);
6988 }
6989
6990 fn visit_children(
6991 self: RenderHandle<Self>,
6992 app: &App,
6993 visitor: &mut dyn FnMut(AnyRenderObject),
6994 ) {
6995 if let Some(child) = self.child(app) {
6996 visitor(child.as_object());
6997 }
6998 }
6999}
7000
7001impl RenderBox for RenderMetaData {
7002 crate::render_box_accessors!();
7003
7004 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7005 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7006 }
7007
7008 fn apply_paint_transform(
7009 self: RenderHandle<Self>,
7010 app: &App,
7011 child: AnyRenderObject,
7012 transform: &mut Matrix4,
7013 ) {
7014 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7015 }
7016
7017 fn hit_test(
7018 self: RenderHandle<Self>,
7019 app: &mut App,
7020 result: &mut BoxHitTestResult<'_>,
7021 position: Offset,
7022 ) -> bool {
7023 RenderProxyBoxWithHitTestBehavior::hit_test(self, app, result, position)
7024 }
7025
7026 fn hit_test_self(self: RenderHandle<Self>, app: &App, position: Offset) -> bool {
7027 RenderProxyBoxWithHitTestBehavior::hit_test_self(self, app, position)
7028 }
7029
7030 fn hit_test_children(
7031 self: RenderHandle<Self>,
7032 app: &mut App,
7033 result: &mut BoxHitTestResult<'_>,
7034 position: Offset,
7035 ) -> bool {
7036 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7037 }
7038
7039 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7040 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7041 }
7042
7043 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7044 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7045 }
7046
7047 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7048 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7049 }
7050
7051 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7052 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7053 }
7054
7055 fn compute_distance_to_actual_baseline(
7056 self: RenderHandle<Self>,
7057 app: &mut App,
7058 baseline: TextBaseline,
7059 ) -> Option<f64> {
7060 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7061 }
7062
7063 fn compute_dry_baseline(
7064 self: RenderHandle<Self>,
7065 app: &mut App,
7066 constraints: BoxConstraints,
7067 baseline: TextBaseline,
7068 ) -> Option<f64> {
7069 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7070 }
7071
7072 fn compute_dry_layout(
7073 self: RenderHandle<Self>,
7074 app: &mut App,
7075 constraints: BoxConstraints,
7076 ) -> Size {
7077 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7078 }
7079}
7080
7081pub struct RenderBackdropFilter {
7086 render_object: RenderObjectData,
7087 render_box: RenderBoxData,
7088 child: RenderObjectWithChildData<AnyRenderBox>,
7089 filter_config: ImageFilterConfig,
7090 blend_mode: BlendMode,
7091 enabled: bool,
7092 backdrop_key: Option<BackdropKey>,
7093}
7094
7095impl RenderBackdropFilter {
7096 pub fn new(
7100 app: &mut App,
7101 filter_config: ImageFilterConfig,
7102 blend_mode: BlendMode,
7103 enabled: bool,
7104 backdrop_key: Option<BackdropKey>,
7105 child: Option<AnyRenderBox>,
7106 ) -> RenderHandle<Self> {
7107 let this = RenderHandle::new_box(
7108 app,
7109 RenderBackdropFilter {
7110 render_object: RenderObjectData::new(),
7111 render_box: RenderBoxData::new(),
7112 child: RenderObjectWithChildData::new(),
7113 filter_config,
7114 blend_mode,
7115 enabled,
7116 backdrop_key,
7117 },
7118 );
7119 this.set_child(app, child);
7120 this
7121 }
7122
7123 pub fn enabled(self: RenderHandle<Self>, app: &App) -> bool {
7125 self.get(app).enabled
7126 }
7127
7128 pub fn set_enabled(self: RenderHandle<Self>, app: &mut App, value: bool) {
7130 if self.get(app).enabled == value {
7131 return;
7132 }
7133 self.get_mut(app).enabled = value;
7134 self.mark_needs_paint(app);
7135 }
7136
7137 pub fn filter(self: RenderHandle<Self>, app: &App) -> ImageFilter {
7142 self.get(app)
7143 .filter_config
7144 .filter()
7145 .expect(
7146 "This getter should only be called when the filter is assigned via the \
7147 `filter` setter.",
7148 )
7149 .clone()
7150 }
7151
7152 pub fn set_filter(self: RenderHandle<Self>, app: &mut App, value: ImageFilter) {
7154 self.set_filter_config(app, ImageFilterConfig::new(value));
7155 }
7156
7157 pub fn filter_config(self: RenderHandle<Self>, app: &App) -> &ImageFilterConfig {
7159 &self.get(app).filter_config
7160 }
7161
7162 pub fn set_filter_config(self: RenderHandle<Self>, app: &mut App, value: ImageFilterConfig) {
7164 if self.get(app).filter_config == value {
7165 return;
7166 }
7167 self.get_mut(app).filter_config = value;
7168 self.mark_needs_paint(app);
7169 }
7170
7171 pub fn blend_mode(self: RenderHandle<Self>, app: &App) -> BlendMode {
7174 self.get(app).blend_mode
7175 }
7176
7177 pub fn set_blend_mode(self: RenderHandle<Self>, app: &mut App, value: BlendMode) {
7179 if self.get(app).blend_mode == value {
7180 return;
7181 }
7182 self.get_mut(app).blend_mode = value;
7183 self.mark_needs_paint(app);
7184 }
7185
7186 pub fn backdrop_key(self: RenderHandle<Self>, app: &App) -> Option<BackdropKey> {
7188 self.get(app).backdrop_key
7189 }
7190
7191 pub fn set_backdrop_key(self: RenderHandle<Self>, app: &mut App, value: Option<BackdropKey>) {
7193 if self.get(app).backdrop_key == value {
7194 return;
7195 }
7196 self.get_mut(app).backdrop_key = value;
7197 self.mark_needs_paint(app);
7198 }
7199}
7200
7201impl RenderObjectWithChildMixin for RenderBackdropFilter {
7202 type ChildType = AnyRenderBox;
7203
7204 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
7205 &self.get(app).child
7206 }
7207
7208 fn child_data_mut(
7209 self: RenderHandle<Self>,
7210 app: &mut App,
7211 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
7212 &mut self.get_mut(app).child
7213 }
7214}
7215
7216impl RenderProxyBoxMixin for RenderBackdropFilter {}
7217
7218impl RenderObject for RenderBackdropFilter {
7219 crate::render_object_accessors!();
7220
7221 fn always_needs_compositing(self: RenderHandle<Self>, app: &App) -> bool {
7222 self.child(app).is_some()
7223 }
7224
7225 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7226 RenderProxyBoxMixin::perform_layout(self, app);
7227 }
7228
7229 fn paint(
7230 self: RenderHandle<Self>,
7231 app: &mut App,
7232 context: &mut PaintingContext,
7233 offset: Offset,
7234 ) {
7235 if !self.get(app).enabled {
7236 RenderProxyBoxMixin::paint(self, app, context, offset);
7237 return;
7238 }
7239 let bounds = offset & self.size(app);
7240 let effective_filter = self
7241 .get(app)
7242 .filter_config
7243 .resolve(ImageFilterContext { bounds });
7244 if self.child(app).is_some() {
7245 debug_assert!(self.as_object().needs_compositing(app));
7246 let (blend_mode, backdrop_key) = {
7247 let this = self.get(app);
7248 (this.blend_mode, this.backdrop_key)
7249 };
7250 let layer = match self.as_object().layer_as::<BackdropFilterLayer>(app) {
7251 Some(layer) => layer,
7252 None => {
7253 let layer = BackdropFilterLayer::new(app);
7254 self.as_object()
7255 .set_layer(app, Some(layer.as_container_layer()));
7256 layer
7257 }
7258 };
7259 layer.set_filter(app, Some(effective_filter));
7260 layer.set_blend_mode(app, blend_mode);
7261 layer.set_backdrop_key(app, backdrop_key);
7262 context.push_layer(
7263 app,
7264 layer.as_container_layer(),
7265 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
7266 offset,
7267 None,
7268 );
7269 } else {
7270 self.as_object().set_layer(app, None);
7271 }
7272 }
7273
7274 fn visit_children(
7275 self: RenderHandle<Self>,
7276 app: &App,
7277 visitor: &mut dyn FnMut(AnyRenderObject),
7278 ) {
7279 if let Some(child) = self.child(app) {
7280 visitor(child.as_object());
7281 }
7282 }
7283}
7284
7285impl RenderBox for RenderBackdropFilter {
7286 crate::render_box_accessors!();
7287
7288 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7289 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7290 }
7291
7292 fn apply_paint_transform(
7293 self: RenderHandle<Self>,
7294 app: &App,
7295 child: AnyRenderObject,
7296 transform: &mut Matrix4,
7297 ) {
7298 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7299 }
7300
7301 fn hit_test_children(
7302 self: RenderHandle<Self>,
7303 app: &mut App,
7304 result: &mut BoxHitTestResult<'_>,
7305 position: Offset,
7306 ) -> bool {
7307 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7308 }
7309
7310 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7311 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7312 }
7313
7314 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7315 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7316 }
7317
7318 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7319 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7320 }
7321
7322 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7323 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7324 }
7325
7326 fn compute_distance_to_actual_baseline(
7327 self: RenderHandle<Self>,
7328 app: &mut App,
7329 baseline: TextBaseline,
7330 ) -> Option<f64> {
7331 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7332 }
7333
7334 fn compute_dry_baseline(
7335 self: RenderHandle<Self>,
7336 app: &mut App,
7337 constraints: BoxConstraints,
7338 baseline: TextBaseline,
7339 ) -> Option<f64> {
7340 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7341 }
7342
7343 fn compute_dry_layout(
7344 self: RenderHandle<Self>,
7345 app: &mut App,
7346 constraints: BoxConstraints,
7347 ) -> Size {
7348 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7349 }
7350}
7351
7352pub struct RenderAnnotatedRegion<T> {
7357 render_object: RenderObjectData,
7358 render_box: RenderBoxData,
7359 child: RenderObjectWithChildData<AnyRenderBox>,
7360 value: Rc<T>,
7361 sized: bool,
7362 layer_handle: LayerHandle<Handle<AnnotatedRegionLayer>>,
7363}
7364
7365impl<T: PartialEq + 'static> RenderAnnotatedRegion<T> {
7366 pub fn new(
7371 app: &mut App,
7372 value: Rc<T>,
7373 sized: bool,
7374 child: Option<AnyRenderBox>,
7375 ) -> RenderHandle<RenderAnnotatedRegion<T>> {
7376 let this = RenderHandle::new_box(
7377 app,
7378 RenderAnnotatedRegion {
7379 render_object: RenderObjectData::new(),
7380 render_box: RenderBoxData::new(),
7381 child: RenderObjectWithChildData::new(),
7382 value,
7383 sized,
7384 layer_handle: LayerHandle::new(),
7385 },
7386 );
7387 this.set_child(app, child);
7388 this
7389 }
7390
7391 pub fn value(self: RenderHandle<Self>, app: &App) -> Rc<T> {
7394 Rc::clone(&self.get(app).value)
7395 }
7396
7397 pub fn set_value(self: RenderHandle<Self>, app: &mut App, new_value: Rc<T>) {
7399 if *self.get(app).value == *new_value {
7400 return;
7401 }
7402 self.get_mut(app).value = new_value;
7403 self.mark_needs_paint(app);
7404 }
7405
7406 pub fn sized(self: RenderHandle<Self>, app: &App) -> bool {
7408 self.get(app).sized
7409 }
7410
7411 pub fn set_sized(self: RenderHandle<Self>, app: &mut App, value: bool) {
7413 if self.get(app).sized == value {
7414 return;
7415 }
7416 self.get_mut(app).sized = value;
7417 self.mark_needs_paint(app);
7418 }
7419}
7420
7421impl<T: PartialEq + 'static> RenderObjectWithChildMixin for RenderAnnotatedRegion<T> {
7422 type ChildType = AnyRenderBox;
7423
7424 fn child_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectWithChildData<AnyRenderBox> {
7425 &self.get(app).child
7426 }
7427
7428 fn child_data_mut(
7429 self: RenderHandle<Self>,
7430 app: &mut App,
7431 ) -> &mut RenderObjectWithChildData<AnyRenderBox> {
7432 &mut self.get_mut(app).child
7433 }
7434}
7435
7436impl<T: PartialEq + 'static> RenderProxyBoxMixin for RenderAnnotatedRegion<T> {}
7437
7438impl<T: PartialEq + 'static> RenderObject for RenderAnnotatedRegion<T> {
7439 crate::render_object_accessors!();
7440
7441 fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
7442 true
7443 }
7444
7445 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7446 RenderProxyBoxMixin::perform_layout(self, app);
7447 }
7448
7449 fn paint(
7450 self: RenderHandle<Self>,
7451 app: &mut App,
7452 context: &mut PaintingContext,
7453 offset: Offset,
7454 ) {
7455 let sized = self.sized(app);
7456 let value: Rc<dyn Any> = self.value(app);
7457 let layer = AnnotatedRegionLayer::new(app, value);
7458 if sized {
7459 layer.set_size(app, Some(self.size(app)));
7460 layer.set_offset(app, offset);
7461 }
7462 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).layer_handle, Some(layer));
7463 context.push_layer(
7464 app,
7465 layer.as_container_layer(),
7466 |app, context, offset| RenderProxyBoxMixin::paint(self, app, context, offset),
7467 offset,
7468 None,
7469 );
7470 }
7471
7472 fn dispose(self: RenderHandle<Self>, app: &mut App) {
7473 LayerHandle::set_layer(app, |app| &mut self.get_mut(app).layer_handle, None);
7474 crate::object::RenderObjectBase::dispose(self, app);
7475 }
7476
7477 fn visit_children(
7478 self: RenderHandle<Self>,
7479 app: &App,
7480 visitor: &mut dyn FnMut(AnyRenderObject),
7481 ) {
7482 if let Some(child) = self.child(app) {
7483 visitor(child.as_object());
7484 }
7485 }
7486}
7487
7488impl<T: PartialEq + 'static> RenderBox for RenderAnnotatedRegion<T> {
7489 crate::render_box_accessors!();
7490
7491 fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
7492 RenderProxyBoxMixin::setup_parent_data(self, app, child);
7493 }
7494
7495 fn apply_paint_transform(
7496 self: RenderHandle<Self>,
7497 app: &App,
7498 child: AnyRenderObject,
7499 transform: &mut Matrix4,
7500 ) {
7501 RenderProxyBoxMixin::apply_paint_transform(self, app, child, transform);
7502 }
7503
7504 fn hit_test_children(
7505 self: RenderHandle<Self>,
7506 app: &mut App,
7507 result: &mut BoxHitTestResult<'_>,
7508 position: Offset,
7509 ) -> bool {
7510 RenderProxyBoxMixin::hit_test_children(self, app, result, position)
7511 }
7512
7513 fn compute_min_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7514 RenderProxyBoxMixin::compute_min_intrinsic_width(self, app, height)
7515 }
7516
7517 fn compute_max_intrinsic_width(self: RenderHandle<Self>, app: &mut App, height: f64) -> f64 {
7518 RenderProxyBoxMixin::compute_max_intrinsic_width(self, app, height)
7519 }
7520
7521 fn compute_min_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7522 RenderProxyBoxMixin::compute_min_intrinsic_height(self, app, width)
7523 }
7524
7525 fn compute_max_intrinsic_height(self: RenderHandle<Self>, app: &mut App, width: f64) -> f64 {
7526 RenderProxyBoxMixin::compute_max_intrinsic_height(self, app, width)
7527 }
7528
7529 fn compute_distance_to_actual_baseline(
7530 self: RenderHandle<Self>,
7531 app: &mut App,
7532 baseline: TextBaseline,
7533 ) -> Option<f64> {
7534 RenderProxyBoxMixin::compute_distance_to_actual_baseline(self, app, baseline)
7535 }
7536
7537 fn compute_dry_baseline(
7538 self: RenderHandle<Self>,
7539 app: &mut App,
7540 constraints: BoxConstraints,
7541 baseline: TextBaseline,
7542 ) -> Option<f64> {
7543 RenderProxyBoxMixin::compute_dry_baseline(self, app, constraints, baseline)
7544 }
7545
7546 fn compute_dry_layout(
7547 self: RenderHandle<Self>,
7548 app: &mut App,
7549 constraints: BoxConstraints,
7550 ) -> Size {
7551 RenderProxyBoxMixin::compute_dry_layout(self, app, constraints)
7552 }
7553}
7554
7555#[cfg(test)]
7556mod tests {
7557 use inset_animation::{k_always_complete_animation, k_always_dismissed_animation};
7558 use inset_embedder::ColorFilter;
7559 use inset_embedder::valo::{self, Op};
7560 use inset_foundation::AppCell;
7561 use inset_foundation::ValueNotifier;
7562 use inset_gestures::HitTestResult;
7563 use inset_painting::BoxDecoration;
7564
7565 use super::*;
7566 use crate::layer::{ErasedLayer, OffsetLayer, PictureLayer};
7567 use crate::pipeline_owner::PipelineOwner;
7568 use inset_embedder::SceneBuilder;
7569
7570 fn sized_box(app: &mut App, size: Size) -> RenderHandle<RenderConstrainedBox> {
7571 RenderConstrainedBox::new(app, BoxConstraints::tight(size), None)
7572 }
7573
7574 struct IntrinsicTestBox {
7577 render_object: RenderObjectData,
7578 render_box: RenderBoxData,
7579 intrinsic: Size,
7580 }
7581
7582 impl RenderObject for IntrinsicTestBox {
7583 crate::render_object_accessors!();
7584
7585 fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
7586 let intrinsic = self.get(app).intrinsic;
7587 let size = self.constraints(app).constrain(intrinsic);
7588 self.set_size(app, size);
7589 }
7590 }
7591
7592 impl RenderBox for IntrinsicTestBox {
7593 crate::render_box_accessors!();
7594
7595 fn compute_min_intrinsic_width(
7596 self: RenderHandle<Self>,
7597 app: &mut App,
7598 _height: f64,
7599 ) -> f64 {
7600 self.get(app).intrinsic.width()
7601 }
7602
7603 fn compute_max_intrinsic_width(
7604 self: RenderHandle<Self>,
7605 app: &mut App,
7606 _height: f64,
7607 ) -> f64 {
7608 self.get(app).intrinsic.width()
7609 }
7610
7611 fn compute_min_intrinsic_height(
7612 self: RenderHandle<Self>,
7613 app: &mut App,
7614 _width: f64,
7615 ) -> f64 {
7616 self.get(app).intrinsic.height()
7617 }
7618
7619 fn compute_max_intrinsic_height(
7620 self: RenderHandle<Self>,
7621 app: &mut App,
7622 _width: f64,
7623 ) -> f64 {
7624 self.get(app).intrinsic.height()
7625 }
7626
7627 fn compute_dry_layout(
7628 self: RenderHandle<Self>,
7629 app: &mut App,
7630 constraints: BoxConstraints,
7631 ) -> Size {
7632 constraints.constrain(self.get(app).intrinsic)
7633 }
7634 }
7635
7636 fn intrinsic_box(app: &mut App, intrinsic: Size) -> RenderHandle<IntrinsicTestBox> {
7637 RenderHandle::new_box(
7638 app,
7639 IntrinsicTestBox {
7640 render_object: RenderObjectData::new(),
7641 render_box: RenderBoxData::new(),
7642 intrinsic,
7643 },
7644 )
7645 }
7646
7647 fn schedule_root_paint(app: &mut App, node: AnyRenderObject) {
7648 let root = OffsetLayer::new(app, Offset::ZERO);
7649 root.as_layer().attach(app, node.id());
7650 node.schedule_initial_paint(app, root.as_container_layer());
7651 }
7652
7653 fn first_frame(app: &mut App, root: AnyRenderBox) -> Handle<PipelineOwner> {
7655 let owner = PipelineOwner::new(app, None, None);
7656 owner.set_root_node(app, Some(root.as_object()));
7657 root.layout(app, BoxConstraints::tight(Size::new(100.0, 100.0)), false);
7658 schedule_root_paint(app, root.as_object());
7659 owner.flush_compositing_bits(app);
7660 owner.flush_paint(app);
7661 owner
7662 }
7663
7664 fn pump_frame(app: &mut App, owner: Handle<PipelineOwner>) {
7665 owner.flush_layout(app);
7666 owner.flush_compositing_bits(app);
7667 owner.flush_paint(app);
7668 }
7669
7670 #[test]
7673 fn constrained_box_intrinsics_enforce_the_additional_constraints() {
7674 let cell = AppCell::new();
7675 let mut app = cell.borrow_mut();
7676 let child = intrinsic_box(&mut app, Size::new(20.0, 30.0));
7677 let loose = RenderConstrainedBox::new(
7678 &mut app,
7679 BoxConstraints::new().min_width(50.0).max_width(60.0),
7680 Some(child.as_box()),
7681 );
7682 assert_eq!(loose.as_box().get_min_intrinsic_width(&mut app, 0.0), 50.0);
7683 assert_eq!(loose.as_box().get_max_intrinsic_width(&mut app, 0.0), 50.0);
7684 assert_eq!(loose.as_box().get_min_intrinsic_height(&mut app, 0.0), 30.0);
7685
7686 let child = intrinsic_box(&mut app, Size::new(20.0, 30.0));
7687 let tight = RenderConstrainedBox::new(
7688 &mut app,
7689 BoxConstraints::tight(Size::new(80.0, 90.0)),
7690 Some(child.as_box()),
7691 );
7692 assert_eq!(tight.as_box().get_max_intrinsic_width(&mut app, 0.0), 80.0);
7693 assert_eq!(tight.as_box().get_max_intrinsic_height(&mut app, 0.0), 90.0);
7694 }
7695
7696 #[test]
7699 fn intrinsic_width_sizes_the_child_to_its_max_intrinsic_width() {
7700 let cell = AppCell::new();
7701 let mut app = cell.borrow_mut();
7702 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7703 let intrinsic = RenderIntrinsicWidth::new(&mut app, None, None, Some(child.as_box()));
7704 intrinsic.layout(&mut app, BoxConstraints::new().max_width(500.0), false);
7705 assert_eq!(intrinsic.size(&app), Size::new(100.0, 40.0));
7706 assert_eq!(child.size(&app), Size::new(100.0, 40.0));
7707
7708 intrinsic.set_step_width(&mut app, Some(30.0));
7709 intrinsic.layout(&mut app, BoxConstraints::new().max_width(500.0), false);
7710 assert_eq!(intrinsic.size(&app), Size::new(120.0, 40.0));
7711 }
7712
7713 #[test]
7715 fn intrinsic_width_dry_layout_matches_its_layout() {
7716 let cell = AppCell::new();
7717 let mut app = cell.borrow_mut();
7718 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7719 let intrinsic = RenderIntrinsicWidth::new(&mut app, None, None, Some(child.as_box()));
7720 let constraints = BoxConstraints::new().max_width(500.0);
7721 let dry = intrinsic.as_box().get_dry_layout(&mut app, constraints);
7722 intrinsic.layout(&mut app, constraints, false);
7723 assert_eq!(dry, intrinsic.size(&app));
7724 }
7725
7726 #[test]
7728 fn intrinsic_height_sizes_the_child_to_its_max_intrinsic_height() {
7729 let cell = AppCell::new();
7730 let mut app = cell.borrow_mut();
7731 let child = intrinsic_box(&mut app, Size::new(100.0, 40.0));
7732 let intrinsic = RenderIntrinsicHeight::new(&mut app, Some(child.as_box()));
7733 intrinsic.layout(&mut app, BoxConstraints::new().max_height(500.0), false);
7734 assert_eq!(intrinsic.size(&app), Size::new(100.0, 40.0));
7735 assert_eq!(
7736 intrinsic
7737 .as_box()
7738 .get_max_intrinsic_width(&mut app, f64::INFINITY),
7739 100.0
7740 );
7741 }
7742
7743 #[test]
7746 fn fitted_box_scales_its_child_into_itself() {
7747 let cell = AppCell::new();
7748 let mut app = cell.borrow_mut();
7749 let child = sized_box(&mut app, Size::new(100.0, 100.0));
7750 let fitted = RenderFittedBox::new(
7751 &mut app,
7752 BoxFit::Contain,
7753 AlignmentGeometry::CENTER,
7754 None,
7755 Some(child.as_box()),
7756 );
7757 fitted.layout(
7758 &mut app,
7759 BoxConstraints::tight(Size::new(50.0, 50.0)),
7760 false,
7761 );
7762 assert_eq!(fitted.size(&app), Size::new(50.0, 50.0));
7763 assert_eq!(child.size(&app), Size::new(100.0, 100.0));
7764
7765 let mut transform = Matrix4::IDENTITY;
7766 RenderBox::apply_paint_transform(fitted, &app, child.as_object(), &mut transform);
7767 assert_eq!(
7768 inset_painting::transform_point(&transform, Offset::new(100.0, 100.0)),
7769 Offset::new(50.0, 50.0)
7770 );
7771 }
7772
7773 #[test]
7776 fn aspect_ratio_sizes_itself_from_the_width() {
7777 let cell = AppCell::new();
7778 let mut app = cell.borrow_mut();
7779 let child = sized_box(&mut app, Size::new(10.0, 10.0));
7780 let aspect = RenderAspectRatio::new(&mut app, 2.0, Some(child.as_box()));
7781 aspect.layout(
7782 &mut app,
7783 BoxConstraints::new().max_width(200.0).max_height(200.0),
7784 false,
7785 );
7786 assert_eq!(aspect.size(&app), Size::new(200.0, 100.0));
7787 assert_eq!(child.size(&app), Size::new(200.0, 100.0));
7788 assert_eq!(
7789 aspect.as_box().get_min_intrinsic_width(&mut app, 50.0),
7790 100.0
7791 );
7792 assert_eq!(
7793 aspect.as_box().get_min_intrinsic_height(&mut app, 50.0),
7794 25.0
7795 );
7796 }
7797
7798 #[test]
7800 fn aspect_ratio_infers_the_width_from_an_unbounded_axis() {
7801 let cell = AppCell::new();
7802 let mut app = cell.borrow_mut();
7803 let aspect = RenderAspectRatio::new(&mut app, 0.5, None);
7804 aspect.layout(&mut app, BoxConstraints::new().max_height(100.0), false);
7805 assert_eq!(aspect.size(&app), Size::new(50.0, 100.0));
7806 }
7807
7808 #[test]
7809 fn constrained_box_without_child() {
7810 let cell = AppCell::new();
7811 let mut app = cell.borrow_mut();
7812 let box_ =
7813 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(80.0, 40.0)), None);
7814 box_.layout(&mut app, BoxConstraints::new(), false);
7815 assert_eq!(box_.size(&app), Size::new(80.0, 40.0));
7816 }
7817
7818 #[test]
7819 fn additional_constraints_change_marks_layout() {
7820 let cell = AppCell::new();
7821 let mut app = cell.borrow_mut();
7822 let box_ =
7823 RenderConstrainedBox::new(&mut app, BoxConstraints::tight(Size::new(10.0, 10.0)), None);
7824 box_.layout(&mut app, BoxConstraints::new(), false);
7825 assert!(!box_.debug_needs_layout(&app));
7826 box_.set_additional_constraints(&mut app, BoxConstraints::tight(Size::new(20.0, 20.0)));
7827 assert!(box_.debug_needs_layout(&app));
7828 box_.layout(&mut app, BoxConstraints::new(), false);
7829 assert_eq!(box_.size(&app), Size::new(20.0, 20.0));
7830 }
7831
7832 #[test]
7834 fn proxy_box_child_gets_empty_parent_data() {
7835 let cell = AppCell::new();
7836 let mut app = cell.borrow_mut();
7837 let child = sized_box(&mut app, Size::new(10.0, 10.0));
7838 let parent = RenderConstrainedBox::new(
7839 &mut app,
7840 BoxConstraints::tight(Size::new(10.0, 10.0)),
7841 Some(child.as_box()),
7842 );
7843 parent.layout(&mut app, BoxConstraints::new(), false);
7844 assert!(child.as_box().parent_data_is::<EmptyParentData>(&app));
7845 }
7846
7847 #[test]
7850 fn render_opacity_composites_only_when_visible() {
7851 let cell = AppCell::new();
7852 let mut app = cell.borrow_mut();
7853 for (opacity, composites) in [(0.0, false), (1.0, true), (0.1, true)] {
7854 let child = sized_box(&mut app, Size::new(1.0, 1.0));
7855 let opacity = RenderOpacity::new(&mut app, opacity, Some(child.as_box()));
7856 assert_eq!(opacity.as_object().is_repaint_boundary(&app), composites);
7857 }
7858 }
7859
7860 #[test]
7862 fn non_painted_layers_are_detached() {
7863 let cell = AppCell::new();
7864 let mut app = cell.borrow_mut();
7865 let inner = RenderDecoratedBox::new(
7866 &mut app,
7867 Box::new(BoxDecoration::new()),
7868 DecorationPosition::Background,
7869 ImageConfiguration::EMPTY,
7870 None,
7871 );
7872 let boundary = RenderRepaintBoundary::new(&mut app, Some(inner.as_box()));
7873 let opacity = RenderOpacity::new(&mut app, 1.0, Some(boundary.as_box()));
7874 let root = RenderRepaintBoundary::new(&mut app, Some(opacity.as_box()));
7876 let owner = first_frame(&mut app, root.as_box());
7877 assert!(!inner.as_object().is_repaint_boundary(&app));
7878 assert!(inner.as_object().debug_layer(&app).is_none());
7879 assert!(boundary.as_object().is_repaint_boundary(&app));
7880 let layer = boundary.as_object().debug_layer(&app).expect("painted");
7881 assert!(layer.as_layer().attached(&app), "this time it painted");
7882
7883 opacity.set_opacity(&mut app, 0.0);
7884 pump_frame(&mut app, owner);
7885 assert!(inner.as_object().debug_layer(&app).is_none());
7886 let layer = boundary.as_object().debug_layer(&app).expect("kept");
7887 assert!(!layer.as_layer().attached(&app), "this time it did not");
7888
7889 opacity.set_opacity(&mut app, 0.5);
7890 pump_frame(&mut app, owner);
7891 let layer = boundary.as_object().debug_layer(&app).expect("kept");
7892 assert!(layer.as_layer().attached(&app), "this time it did again");
7893 }
7894
7895 #[test]
7896 fn animated_opacity_follows_its_animation() {
7897 let cell = AppCell::new();
7898 let mut app = cell.borrow_mut();
7899 let child = sized_box(&mut app, Size::new(1.0, 1.0));
7900 let dismissed = k_always_dismissed_animation(&mut app);
7901 let complete = k_always_complete_animation(&mut app);
7902 let fade = RenderAnimatedOpacity::new(&mut app, dismissed, Some(child.as_box()));
7903 assert!(!fade.as_object().is_repaint_boundary(&app));
7904 let root = RenderRepaintBoundary::new(&mut app, Some(fade.as_box()));
7905 let owner = first_frame(&mut app, root.as_box());
7906
7907 fade.set_opacity(&mut app, complete);
7908 assert!(fade.as_object().is_repaint_boundary(&app));
7909 assert!(fade.as_object().debug_needs_paint(&app));
7910 pump_frame(&mut app, owner);
7911 let layer = fade.as_object().debug_layer(&app).expect("a boundary now");
7912 let opacity = app
7913 .handle::<OpacityLayer>(layer.id())
7914 .expect("an OpacityLayer");
7915 assert_eq!(opacity.alpha(&app), Some(255));
7916 }
7917
7918 #[test]
7919 fn decorated_box_paints_its_decoration() {
7920 let cell = AppCell::new();
7921 let mut app = cell.borrow_mut();
7922 let decorated = RenderDecoratedBox::new(
7923 &mut app,
7924 Box::new(BoxDecoration::new().color(Color::from_argb(255, 255, 0, 0))),
7925 DecorationPosition::Background,
7926 ImageConfiguration::EMPTY,
7927 None,
7928 );
7929 let root = RenderRepaintBoundary::new(&mut app, Some(decorated.as_box()));
7930 first_frame(&mut app, root.as_box());
7931 let ops = scene_ops(&mut app, root.as_object());
7932 assert!(
7933 ops.iter()
7934 .any(|op| matches!(op, inset_embedder::valo::Op::DrawDisplayList { .. })),
7935 "{ops:?}"
7936 );
7937 }
7938
7939 fn opaque_leaf(app: &mut App) -> RenderHandle<RenderPointerListener> {
7941 RenderPointerListener::new(app, HitTestBehavior::Opaque, None)
7942 }
7943
7944 const RED: Color = Color::from_argb(255, 255, 0, 0);
7945 const BLUE: Color = Color::from_argb(255, 0, 0, 255);
7946
7947 fn red_box(app: &mut App) -> RenderHandle<RenderColoredBox> {
7948 RenderColoredBox::new(app, RED, true, None)
7949 }
7950
7951 fn hit_test(app: &mut App, target: AnyRenderBox, position: Offset) -> (bool, usize) {
7953 let mut result = HitTestResult::new();
7954 let is_hit = target.hit_test(app, &mut BoxHitTestResult::wrap(&mut result), position);
7955 (is_hit, result.path().len())
7956 }
7957
7958 fn picture_ops(app: &App, boundary: AnyRenderObject) -> Vec<Op> {
7960 let layer = boundary.debug_layer(app).expect("painted");
7961 layer
7962 .depth_first_iterate_children(app)
7963 .into_iter()
7964 .filter_map(|child| {
7965 app.handle::<PictureLayer>(child.id())
7966 .and_then(|picture| picture.picture(app).map(|p| p.ops().to_vec()))
7967 })
7968 .flatten()
7969 .collect()
7970 }
7971
7972 fn picture_has_clip(app: &App, boundary: AnyRenderObject) -> bool {
7973 picture_ops(app, boundary)
7974 .iter()
7975 .any(|op| matches!(op, Op::ClipPath { .. }))
7976 }
7977
7978 fn drawn_rects(app: &App, boundary: AnyRenderObject) -> Vec<(valo::Rect, valo::Color)> {
7980 picture_ops(app, boundary)
7981 .iter()
7982 .filter_map(|op| match op {
7983 Op::DrawRect { rect, paint, .. } => Some((*rect, paint.color)),
7984 _ => None,
7985 })
7986 .collect()
7987 }
7988
7989 fn fill(rect: Rect, color: Color) -> (valo::Rect, valo::Color) {
7990 (rect.into(), color.into())
7991 }
7992
7993 #[test]
7994 fn limited_box_limits_only_unbounded_constraints() {
7995 let cell = AppCell::new();
7996 let mut app = cell.borrow_mut();
7997 let child = opaque_leaf(&mut app);
7998 let limited = RenderLimitedBox::new(&mut app, 100.0, 50.0, Some(child.as_box()));
7999
8000 limited.layout(&mut app, BoxConstraints::new(), false);
8001 assert_eq!(limited.size(&app), Size::new(100.0, 50.0));
8002
8003 limited.layout(
8004 &mut app,
8005 BoxConstraints::loose(Size::new(30.0, 30.0)),
8006 false,
8007 );
8008 assert_eq!(
8009 limited.size(&app),
8010 Size::new(30.0, 30.0),
8011 "a bounded constraint is left alone"
8012 );
8013 }
8014
8015 #[test]
8016 fn limited_box_without_child_is_empty() {
8017 let cell = AppCell::new();
8018 let mut app = cell.borrow_mut();
8019 let limited = RenderLimitedBox::new(&mut app, 100.0, 50.0, None);
8020 limited.layout(&mut app, BoxConstraints::new(), false);
8021 assert_eq!(limited.size(&app), Size::ZERO);
8022 }
8023
8024 struct LeftHalfClipper;
8026
8027 impl CustomClipper<Rect> for LeftHalfClipper {
8028 fn get_clip(&self, size: Size) -> Rect {
8029 Rect::from_ltwh(0.0, 0.0, size.width() / 2.0, size.height())
8030 }
8031
8032 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<Rect>) -> bool {
8033 false
8034 }
8035
8036 fn as_any(&self) -> &dyn Any {
8037 self
8038 }
8039 }
8040
8041 impl CustomClipper<RRect> for LeftHalfClipper {
8042 fn get_clip(&self, size: Size) -> RRect {
8043 RRect::from_rect_xy(
8044 Rect::from_ltwh(0.0, 0.0, size.width() / 2.0, size.height()),
8045 0.0,
8046 0.0,
8047 )
8048 }
8049
8050 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<RRect>) -> bool {
8051 false
8052 }
8053
8054 fn as_any(&self) -> &dyn Any {
8055 self
8056 }
8057 }
8058
8059 struct NotifyingClipper {
8061 reclip: Rc<dyn Listenable>,
8062 }
8063
8064 impl CustomClipper<Rect> for NotifyingClipper {
8065 fn reclip(&self) -> Option<&Rc<dyn Listenable>> {
8066 Some(&self.reclip)
8067 }
8068
8069 fn get_clip(&self, size: Size) -> Rect {
8070 Offset::ZERO & size
8071 }
8072
8073 fn should_reclip(&self, _old_clipper: &dyn CustomClipper<Rect>) -> bool {
8074 false
8075 }
8076
8077 fn as_any(&self) -> &dyn Any {
8078 self
8079 }
8080 }
8081
8082 #[test]
8083 fn clip_rect_pushes_its_clipper_and_clips_hit_tests() {
8084 let cell = AppCell::new();
8085 let mut app = cell.borrow_mut();
8086 let child = opaque_leaf(&mut app);
8087 let clipper: Rc<dyn CustomClipper<Rect>> = Rc::new(LeftHalfClipper);
8088 let clip = RenderClipRect::new(
8089 &mut app,
8090 Some(clipper),
8091 Clip::HardEdge,
8092 Some(child.as_box()),
8093 );
8094 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8095 first_frame(&mut app, root.as_box());
8096
8097 let ops = picture_ops(&app, root.as_object());
8098 let clip_path = ops
8099 .iter()
8100 .find_map(|op| match op {
8101 Op::ClipPath { path, .. } => Some(path),
8102 _ => None,
8103 })
8104 .expect("the recording clips");
8105 assert_eq!(
8106 clip_path.bounds(),
8107 Rect::from_ltwh(0.0, 0.0, 50.0, 100.0).into()
8108 );
8109
8110 assert!(hit_test(&mut app, clip.as_box(), Offset::new(25.0, 50.0)).0);
8111 assert!(
8112 !hit_test(&mut app, clip.as_box(), Offset::new(75.0, 50.0)).0,
8113 "outside the clipper's clip"
8114 );
8115 }
8116
8117 #[test]
8118 fn clip_rect_without_clipping_paints_its_child_directly() {
8119 let cell = AppCell::new();
8120 let mut app = cell.borrow_mut();
8121 let child = red_box(&mut app);
8122 let clip = RenderClipRect::new(&mut app, None, Clip::None, Some(child.as_box()));
8123 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8124 first_frame(&mut app, root.as_box());
8125
8126 assert!(
8127 !picture_has_clip(&app, root.as_object()),
8128 "Clip::None paints the child directly"
8129 );
8130 assert_eq!(
8131 drawn_rects(&app, root.as_object()),
8132 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8133 );
8134 }
8135
8136 #[test]
8137 fn clip_rrect_pushes_its_border_radius() {
8138 let cell = AppCell::new();
8139 let mut app = cell.borrow_mut();
8140 let child = opaque_leaf(&mut app);
8141 let clip = RenderClipRRect::new(
8142 &mut app,
8143 BorderRadiusGeometry::circular(20.0),
8144 None,
8145 Clip::AntiAlias,
8146 None,
8147 Some(child.as_box()),
8148 );
8149 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8150 first_frame(&mut app, root.as_box());
8151
8152 let bounds = Rect::from_ltwh(0.0, 0.0, 100.0, 100.0);
8153 let ops = picture_ops(&app, root.as_object());
8154 let clip_path = ops
8155 .iter()
8156 .find_map(|op| match op {
8157 Op::ClipPath { path, .. } => Some(path),
8158 _ => None,
8159 })
8160 .expect("the recording starts with the clip");
8161 assert_eq!(clip_path.bounds(), bounds.into());
8162
8163 assert!(
8164 hit_test(&mut app, clip.as_box(), Offset::new(99.0, 99.0)).0,
8165 "without a clipper the hit test is not clipped, as in Dart"
8166 );
8167 }
8168
8169 #[test]
8170 fn clip_rrect_clips_hit_tests_to_its_clipper() {
8171 let cell = AppCell::new();
8172 let mut app = cell.borrow_mut();
8173 let child = opaque_leaf(&mut app);
8174 let clipper: Rc<dyn CustomClipper<RRect>> = Rc::new(LeftHalfClipper);
8175 let clip = RenderClipRRect::new(
8176 &mut app,
8177 BorderRadiusGeometry::ZERO,
8178 Some(clipper),
8179 Clip::AntiAlias,
8180 None,
8181 Some(child.as_box()),
8182 );
8183 clip.layout(
8184 &mut app,
8185 BoxConstraints::tight(Size::new(100.0, 100.0)),
8186 false,
8187 );
8188
8189 assert!(hit_test(&mut app, clip.as_box(), Offset::new(25.0, 50.0)).0);
8190 assert!(!hit_test(&mut app, clip.as_box(), Offset::new(75.0, 50.0)).0);
8191 }
8192
8193 #[test]
8195 fn clip_rect_reclips_on_notification_and_on_resize() {
8196 let cell = AppCell::new();
8197 let mut app = cell.borrow_mut();
8198 let reclip = app.create(ValueNotifier::new(0));
8199 let clipper: Rc<dyn CustomClipper<Rect>> = Rc::new(NotifyingClipper {
8200 reclip: Rc::new(reclip),
8201 });
8202 let child = red_box(&mut app);
8203 let clip = RenderClipRect::new(
8204 &mut app,
8205 Some(clipper),
8206 Clip::HardEdge,
8207 Some(child.as_box()),
8208 );
8209 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8210 let owner = first_frame(&mut app, root.as_box());
8211 assert!(clip.custom_clip_data(&app).clip.is_some());
8212
8213 reclip.set_value(&mut app, 1);
8214 assert!(
8215 clip.custom_clip_data(&app).clip.is_none(),
8216 "the clipper's notification dropped the cached clip"
8217 );
8218 assert!(clip.as_object().debug_needs_paint(&app));
8219 pump_frame(&mut app, owner);
8220 assert!(clip.custom_clip_data(&app).clip.is_some());
8221
8222 clip.layout(
8223 &mut app,
8224 BoxConstraints::tight(Size::new(50.0, 50.0)),
8225 false,
8226 );
8227 assert!(
8228 clip.custom_clip_data(&app).clip.is_none(),
8229 "a new size dropped the cached clip"
8230 );
8231 }
8232
8233 #[test]
8234 fn transform_paints_under_its_matrix() {
8235 let cell = AppCell::new();
8236 let mut app = cell.borrow_mut();
8237 let child = red_box(&mut app);
8238 let transform = RenderTransform::new(
8239 &mut app,
8240 Matrix4::scale(2.0, 2.0),
8241 None,
8242 None,
8243 None,
8244 true,
8245 Some(child.as_box()),
8246 );
8247 let root = RenderRepaintBoundary::new(&mut app, Some(transform.as_box()));
8248 first_frame(&mut app, root.as_box());
8249
8250 let ops = picture_ops(&app, root.as_object());
8251 let pushed = ops.iter().find_map(|op| match op {
8252 Op::Transform(transform) => Some(*transform),
8253 _ => None,
8254 });
8255 assert_eq!(pushed, Some(Matrix4::scale(2.0, 2.0)));
8256 }
8257
8258 #[test]
8260 fn transform_by_a_translation_paints_at_an_offset() {
8261 let cell = AppCell::new();
8262 let mut app = cell.borrow_mut();
8263 let child = red_box(&mut app);
8264 let transform = RenderTransform::new(
8265 &mut app,
8266 Matrix4::translation(10.0, 20.0),
8267 None,
8268 None,
8269 None,
8270 true,
8271 Some(child.as_box()),
8272 );
8273 let root = RenderRepaintBoundary::new(&mut app, Some(transform.as_box()));
8274 first_frame(&mut app, root.as_box());
8275
8276 assert!(
8277 !picture_ops(&app, root.as_object())
8278 .iter()
8279 .any(|op| matches!(op, Op::Transform(_))),
8280 "a translation is folded into the child's paint offset"
8281 );
8282 assert_eq!(
8283 drawn_rects(&app, root.as_object()),
8284 [fill(Rect::from_ltwh(10.0, 20.0, 100.0, 100.0), RED)]
8285 );
8286 }
8287
8288 #[test]
8289 fn transform_hit_tests_through_its_matrix() {
8290 let cell = AppCell::new();
8291 let mut app = cell.borrow_mut();
8292 let child = opaque_leaf(&mut app);
8293 let transform = RenderTransform::new(
8294 &mut app,
8295 Matrix4::scale(2.0, 2.0),
8296 None,
8297 None,
8298 None,
8299 true,
8300 Some(child.as_box()),
8301 );
8302 transform.layout(
8303 &mut app,
8304 BoxConstraints::tight(Size::new(100.0, 100.0)),
8305 false,
8306 );
8307
8308 assert_eq!(
8309 hit_test(&mut app, transform.as_box(), Offset::new(150.0, 50.0)),
8310 (true, 1),
8311 "the child covers twice the box, and the transform does not add itself"
8312 );
8313
8314 transform.set_transform_hit_tests(&mut app, false);
8315 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(150.0, 50.0)).0);
8316 assert!(hit_test(&mut app, transform.as_box(), Offset::new(50.0, 50.0)).0);
8317 }
8318
8319 #[test]
8321 fn transform_scales_around_its_alignment_and_origin() {
8322 let cell = AppCell::new();
8323 let mut app = cell.borrow_mut();
8324 let child = opaque_leaf(&mut app);
8325 let transform = RenderTransform::new(
8326 &mut app,
8327 Matrix4::scale(2.0, 2.0),
8328 None,
8329 Some(AlignmentGeometry::CENTER),
8330 None,
8331 true,
8332 Some(child.as_box()),
8333 );
8334 transform.layout(
8335 &mut app,
8336 BoxConstraints::tight(Size::new(100.0, 100.0)),
8337 false,
8338 );
8339 assert!(hit_test(&mut app, transform.as_box(), Offset::new(140.0, 140.0)).0);
8340 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(160.0, 160.0)).0);
8341
8342 transform.set_alignment(&mut app, None);
8343 transform.set_origin(&mut app, Some(Offset::new(50.0, 50.0)));
8344 assert!(
8345 hit_test(&mut app, transform.as_box(), Offset::new(140.0, 140.0)).0,
8346 "an origin at the centre is the same conjugation"
8347 );
8348 assert!(!hit_test(&mut app, transform.as_box(), Offset::new(160.0, 160.0)).0);
8349 }
8350
8351 #[test]
8352 fn transform_applies_its_paint_transform_to_the_child() {
8353 let cell = AppCell::new();
8354 let mut app = cell.borrow_mut();
8355 let child = opaque_leaf(&mut app);
8356 let transform = RenderTransform::new(
8357 &mut app,
8358 Matrix4::translation(10.0, 20.0),
8359 None,
8360 None,
8361 None,
8362 true,
8363 Some(child.as_box()),
8364 );
8365 let mut matrix = Matrix4::IDENTITY;
8366 RenderBox::apply_paint_transform(transform, &app, child.as_object(), &mut matrix);
8367 assert_eq!(matrix, Matrix4::translation(10.0, 20.0));
8368 }
8369
8370 #[test]
8371 fn fractional_translation_offsets_paint_and_hits() {
8372 let cell = AppCell::new();
8373 let mut app = cell.borrow_mut();
8374 let child = red_box(&mut app);
8375 let translated = RenderFractionalTranslation::new(
8376 &mut app,
8377 Offset::new(0.5, 0.0),
8378 true,
8379 Some(child.as_box()),
8380 );
8381 let root = RenderRepaintBoundary::new(&mut app, Some(translated.as_box()));
8382 first_frame(&mut app, root.as_box());
8383
8384 assert_eq!(
8385 drawn_rects(&app, root.as_object()),
8386 [fill(Rect::from_ltwh(50.0, 0.0, 100.0, 100.0), RED)],
8387 "half the width to the right"
8388 );
8389
8390 assert!(hit_test(&mut app, translated.as_box(), Offset::new(75.0, 50.0)).0);
8391 assert!(!hit_test(&mut app, translated.as_box(), Offset::new(25.0, 50.0)).0);
8392
8393 translated.set_transform_hit_tests(&mut app, false);
8394 assert!(
8395 hit_test(&mut app, translated.as_box(), Offset::new(25.0, 50.0)).0,
8396 "an untransformed hit test reaches the child where it was laid out"
8397 );
8398 }
8399
8400 #[test]
8401 fn ignore_pointer_is_invisible_to_hit_testing() {
8402 let cell = AppCell::new();
8403 let mut app = cell.borrow_mut();
8404 let child = opaque_leaf(&mut app);
8405 let ignoring = RenderIgnorePointer::new(&mut app, true, Some(child.as_box()));
8406 ignoring.layout(
8407 &mut app,
8408 BoxConstraints::tight(Size::new(100.0, 100.0)),
8409 false,
8410 );
8411
8412 assert_eq!(
8413 hit_test(&mut app, ignoring.as_box(), Offset::new(50.0, 50.0)),
8414 (false, 0)
8415 );
8416
8417 ignoring.set_ignoring(&mut app, false);
8418 assert_eq!(
8419 hit_test(&mut app, ignoring.as_box(), Offset::new(50.0, 50.0)),
8420 (true, 2),
8421 "the child and the ignore pointer itself"
8422 );
8423 }
8424
8425 #[test]
8426 fn absorb_pointer_takes_the_hit_from_its_subtree() {
8427 let cell = AppCell::new();
8428 let mut app = cell.borrow_mut();
8429 let child = opaque_leaf(&mut app);
8430 let absorbing = RenderAbsorbPointer::new(&mut app, true, Some(child.as_box()));
8431 absorbing.layout(
8432 &mut app,
8433 BoxConstraints::tight(Size::new(100.0, 100.0)),
8434 false,
8435 );
8436
8437 assert_eq!(
8438 hit_test(&mut app, absorbing.as_box(), Offset::new(50.0, 50.0)),
8439 (true, 0),
8440 "hit testing stops here, and nothing is added to the path"
8441 );
8442 assert_eq!(
8443 hit_test(&mut app, absorbing.as_box(), Offset::new(150.0, 50.0)),
8444 (false, 0)
8445 );
8446
8447 absorbing.set_absorbing(&mut app, false);
8448 assert_eq!(
8449 hit_test(&mut app, absorbing.as_box(), Offset::new(50.0, 50.0)),
8450 (true, 2)
8451 );
8452 }
8453
8454 #[test]
8455 fn offstage_lays_out_without_painting_or_hit_testing() {
8456 let cell = AppCell::new();
8457 let mut app = cell.borrow_mut();
8458 let child = red_box(&mut app);
8459 let offstage = RenderOffstage::new(&mut app, true, Some(child.as_box()));
8460 let root = RenderRepaintBoundary::new(&mut app, Some(offstage.as_box()));
8461 let owner = first_frame(&mut app, root.as_box());
8462
8463 assert!(RenderObject::sized_by_parent(offstage, &app));
8464 assert_eq!(child.size(&app), Size::new(100.0, 100.0), "still laid out");
8465 assert!(
8466 !picture_has_clip(&app, root.as_object()),
8467 "offstage paints nothing"
8468 );
8469 assert_eq!(
8470 hit_test(&mut app, offstage.as_box(), Offset::new(50.0, 50.0)),
8471 (false, 0)
8472 );
8473 assert!(!offstage.paints_child(&app, child.as_box()));
8474
8475 offstage.set_offstage(&mut app, false);
8476 pump_frame(&mut app, owner);
8477 assert_eq!(
8478 drawn_rects(&app, root.as_object()),
8479 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8480 );
8481 assert!(hit_test(&mut app, offstage.as_box(), Offset::new(50.0, 50.0)).0);
8482 assert!(offstage.paints_child(&app, child.as_box()));
8483 }
8484
8485 #[test]
8486 fn colored_box_fills_its_bounds() {
8487 let cell = AppCell::new();
8488 let mut app = cell.borrow_mut();
8489 let colored = red_box(&mut app);
8490 let root = RenderRepaintBoundary::new(&mut app, Some(colored.as_box()));
8491 first_frame(&mut app, root.as_box());
8492
8493 assert_eq!(
8494 drawn_rects(&app, root.as_object()),
8495 [fill(Rect::from_ltwh(0.0, 0.0, 100.0, 100.0), RED)]
8496 );
8497 assert_eq!(
8498 hit_test(&mut app, colored.as_box(), Offset::new(50.0, 50.0)),
8499 (true, 1),
8500 "an opaque box is hit by itself"
8501 );
8502 }
8503
8504 #[test]
8505 fn colored_box_paints_its_child_over_the_color() {
8506 let cell = AppCell::new();
8507 let mut app = cell.borrow_mut();
8508 let child = red_box(&mut app);
8509 let colored = RenderColoredBox::new(&mut app, BLUE, true, Some(child.as_box()));
8510 let root = RenderRepaintBoundary::new(&mut app, Some(colored.as_box()));
8511 first_frame(&mut app, root.as_box());
8512
8513 let bounds = Rect::from_ltwh(0.0, 0.0, 100.0, 100.0);
8514 assert_eq!(
8515 drawn_rects(&app, root.as_object()),
8516 [fill(bounds, BLUE), fill(bounds, RED)]
8517 );
8518 }
8519
8520 #[test]
8521 fn meta_data_carries_its_payload_and_hit_tests_by_behavior() {
8522 let cell = AppCell::new();
8523 let mut app = cell.borrow_mut();
8524 let payload: Rc<dyn Any> = Rc::new(42u32);
8525 let opaque = RenderMetaData::new(
8526 &mut app,
8527 Some(Rc::clone(&payload)),
8528 HitTestBehavior::Opaque,
8529 None,
8530 );
8531 opaque.layout(
8532 &mut app,
8533 BoxConstraints::tight(Size::new(10.0, 10.0)),
8534 false,
8535 );
8536 assert_eq!(
8537 opaque
8538 .meta_data(&app)
8539 .and_then(|data| data.downcast::<u32>().ok())
8540 .as_deref(),
8541 Some(&42)
8542 );
8543 let mut result = HitTestResult::new();
8544 assert!(opaque.as_box().hit_test(
8545 &mut app,
8546 &mut BoxHitTestResult::wrap(&mut result),
8547 Offset::new(5.0, 5.0)
8548 ));
8549 assert_eq!(result.path().len(), 1);
8550
8551 let deferring = RenderMetaData::new(&mut app, None, HitTestBehavior::DeferToChild, None);
8552 deferring.layout(
8553 &mut app,
8554 BoxConstraints::tight(Size::new(10.0, 10.0)),
8555 false,
8556 );
8557 let mut result = HitTestResult::new();
8558 assert!(!deferring.as_box().hit_test(
8559 &mut app,
8560 &mut BoxHitTestResult::wrap(&mut result),
8561 Offset::new(5.0, 5.0)
8562 ));
8563 assert!(result.path().is_empty());
8564
8565 let child = opaque_leaf(&mut app);
8567 deferring.set_child(&mut app, Some(child.as_box()));
8568 deferring.layout(
8569 &mut app,
8570 BoxConstraints::tight(Size::new(10.0, 10.0)),
8571 false,
8572 );
8573 let mut result = HitTestResult::new();
8574 assert!(deferring.as_box().hit_test(
8575 &mut app,
8576 &mut BoxHitTestResult::wrap(&mut result),
8577 Offset::new(5.0, 5.0)
8578 ));
8579 assert_eq!(result.path().len(), 2, "the child, then the meta data");
8580 }
8581
8582 fn scene_ops(app: &mut App, root: AnyRenderObject) -> Vec<Op> {
8584 let scene = root
8585 .debug_layer(app)
8586 .expect("painted")
8587 .build_scene(app, SceneBuilder::new());
8588 inset_embedder::flattened_ops(&inset_embedder::slices(&scene, |_| None).picture_with_room())
8589 }
8590
8591 #[test]
8592 fn a_backdrop_filter_blurs_under_its_bounds_before_its_child_paints() {
8593 let cell = AppCell::new();
8594 let mut app = cell.borrow_mut();
8595 let child = RenderColoredBox::new(&mut app, Color::new(0xFF00FF00), true, None);
8596 let filter = RenderBackdropFilter::new(
8597 &mut app,
8598 ImageFilterConfig::new(ImageFilter::blur(6.0, 6.0)),
8599 BlendMode::SrcOver,
8600 true,
8601 None,
8602 Some(child.as_box()),
8603 );
8604 let root = RenderRepaintBoundary::new(&mut app, Some(filter.as_box()));
8605 let owner = first_frame(&mut app, root.as_box());
8606 let ops = scene_ops(&mut app, root.as_object());
8607 let blur = ops
8608 .iter()
8609 .position(|op| {
8610 matches!(
8611 op,
8612 Op::SaveLayer {
8613 backdrop: Some(_),
8614 ..
8615 }
8616 )
8617 })
8618 .expect("a backdrop layer");
8619 let draw = ops
8620 .iter()
8621 .position(|op| matches!(op, Op::DrawRect { .. }))
8622 .expect("the child's paint");
8623 assert!(blur < draw, "the blur precedes the child: {ops:?}");
8624 if let Op::SaveLayer {
8625 backdrop: Some(backdrop),
8626 ..
8627 } = &ops[blur]
8628 {
8629 assert_eq!(
8630 backdrop.filter,
8631 inset_embedder::valo::ImageFilter::blur(6.0, 6.0)
8632 );
8633 assert_eq!(backdrop.shared_key, None);
8634 }
8635
8636 let key = BackdropKey::new();
8637 filter.set_backdrop_key(&mut app, Some(key));
8638 pump_frame(&mut app, owner);
8639 let ops = scene_ops(&mut app, root.as_object());
8640 assert!(
8641 ops.iter().any(|op| matches!(
8642 op,
8643 Op::SaveLayer {
8644 backdrop: Some(valo::Backdrop {
8645 shared_key: Some(_),
8646 ..
8647 }),
8648 ..
8649 }
8650 )),
8651 "a keyed filter shares its blur: {ops:?}"
8652 );
8653
8654 filter.set_enabled(&mut app, false);
8655 pump_frame(&mut app, owner);
8656 let ops = scene_ops(&mut app, root.as_object());
8657 assert!(
8658 !ops.iter().any(|op| matches!(
8659 op,
8660 Op::SaveLayer {
8661 backdrop: Some(_),
8662 ..
8663 }
8664 )),
8665 "disabled paints the child only: {ops:?}"
8666 );
8667 }
8668
8669 #[test]
8670 fn a_composed_backdrop_filter_reaches_the_backdrop_whole() {
8671 let cell = AppCell::new();
8672 let mut app = cell.borrow_mut();
8673 let child = RenderColoredBox::new(&mut app, Color::new(0xFF00FF00), true, None);
8674 let saturation = ColorFilter::saturation(1.8);
8675 let filter = RenderBackdropFilter::new(
8676 &mut app,
8677 ImageFilterConfig::compose(
8678 ImageFilterConfig::new(ImageFilter::Color(saturation)),
8679 ImageFilterConfig::blur().sigma_x(4.0),
8680 ),
8681 BlendMode::SrcOver,
8682 true,
8683 None,
8684 Some(child.as_box()),
8685 );
8686 let root = RenderRepaintBoundary::new(&mut app, Some(filter.as_box()));
8687 first_frame(&mut app, root.as_box());
8688 let ops = scene_ops(&mut app, root.as_object());
8689 let composed = valo::ImageFilter::compose(
8690 valo::ImageFilter::Color(saturation.to_valo()),
8691 valo::ImageFilter::blur(4.0, 0.0),
8692 );
8693 assert!(
8694 ops.iter().any(|op| matches!(
8695 op,
8696 Op::SaveLayer {
8697 backdrop: Some(backdrop),
8698 ..
8699 } if backdrop.filter == composed
8700 )),
8701 "the saturation and the blur reach the backdrop in their order: {ops:?}"
8702 );
8703 }
8704
8705 #[test]
8706 fn clip_oval_hit_tests_inside_the_inscribed_oval_and_clips_with_its_path() {
8707 let cell = AppCell::new();
8708 let mut app = cell.borrow_mut();
8709 let child = opaque_leaf(&mut app);
8710 let oval = RenderClipOval::new(&mut app, None, Clip::AntiAlias, Some(child.as_box()));
8711 let root = RenderRepaintBoundary::new(&mut app, Some(oval.as_box()));
8712 first_frame(&mut app, root.as_box());
8713 let hit = |app: &mut App, x: f64, y: f64| {
8714 let mut result = HitTestResult::new();
8715 oval.as_box().hit_test(
8716 app,
8717 &mut BoxHitTestResult::wrap(&mut result),
8718 Offset::new(x, y),
8719 )
8720 };
8721 assert!(hit(&mut app, 50.0, 50.0), "the center is inside");
8722 assert!(!hit(&mut app, 2.0, 2.0), "a corner is outside the oval");
8723 assert!(
8724 picture_has_clip(&app, root.as_object()),
8725 "an oval clips with a path"
8726 );
8727 }
8728
8729 #[test]
8730 fn clip_path_uses_its_clipper_for_hit_tests_and_the_rect_by_default() {
8731 struct Triangle;
8732 impl CustomClipper<Arc<Path>> for Triangle {
8733 fn get_clip(&self, size: Size) -> Arc<Path> {
8734 let mut path = PathBuilder::new();
8735 path.move_to(Point::new(0.0, 0.0));
8736 path.line_to(Point::new(size.width() as f32, 0.0));
8737 path.line_to(Point::new(0.0, size.height() as f32));
8738 path.close();
8739 path.build()
8740 }
8741
8742 fn should_reclip(&self, _old: &dyn CustomClipper<Arc<Path>>) -> bool {
8743 false
8744 }
8745
8746 fn as_any(&self) -> &dyn Any {
8747 self
8748 }
8749 }
8750 let cell = AppCell::new();
8751 let mut app = cell.borrow_mut();
8752 let child = opaque_leaf(&mut app);
8753 let clip = RenderClipPath::new(
8754 &mut app,
8755 Some(Rc::new(Triangle)),
8756 Clip::AntiAlias,
8757 Some(child.as_box()),
8758 );
8759 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8760 first_frame(&mut app, root.as_box());
8761 let hit = |app: &mut App, x: f64, y: f64| {
8762 let mut result = HitTestResult::new();
8763 clip.as_box().hit_test(
8764 app,
8765 &mut BoxHitTestResult::wrap(&mut result),
8766 Offset::new(x, y),
8767 )
8768 };
8769 assert!(hit(&mut app, 10.0, 10.0), "inside the triangle");
8770 assert!(!hit(&mut app, 90.0, 90.0), "outside the triangle");
8771
8772 let plain = RenderClipPath::new(&mut app, None, Clip::HardEdge, None);
8773 plain.layout(
8774 &mut app,
8775 BoxConstraints::tight(Size::new(30.0, 20.0)),
8776 false,
8777 );
8778 assert!(
8779 plain
8780 .default_clip(&app)
8781 .contains(Point::new(29.0, 19.0), FillRule::NonZero),
8782 "the default clip is the box's rect"
8783 );
8784 }
8785
8786 #[test]
8787 fn clip_rsuperellipse_resolves_its_border_radius_and_clips_with_a_path() {
8788 let cell = AppCell::new();
8789 let mut app = cell.borrow_mut();
8790 let child = RenderConstrainedBox::new(&mut app, BoxConstraints::expand(None, None), None);
8791 let clip = RenderClipRSuperellipse::new(
8792 &mut app,
8793 BorderRadiusGeometry::circular(12.0),
8794 None,
8795 Clip::AntiAlias,
8796 Some(TextDirection::Ltr),
8797 Some(child.as_box()),
8798 );
8799 let root = RenderRepaintBoundary::new(&mut app, Some(clip.as_box()));
8800 first_frame(&mut app, root.as_box());
8801 clip.update_clip(&mut app);
8802 assert_eq!(clip.clip(&app).tl_radius_x, 12.0);
8803 assert_eq!(
8804 clip.clip(&app).outer_rect(),
8805 Rect::from_ltwh(0.0, 0.0, 100.0, 100.0)
8806 );
8807 assert!(
8808 picture_has_clip(&app, root.as_object()),
8809 "a superellipse clips with its path"
8810 );
8811 clip.set_border_radius(&mut app, BorderRadiusGeometry::circular(4.0));
8812 assert!(
8813 clip.custom_clip_data(&app).clip.is_none(),
8814 "a new radius marks the clip"
8815 );
8816 }
8817
8818 #[test]
8819 fn a_shape_border_clipper_clips_to_the_shape_and_reclips_when_it_changes() {
8820 let square: Box<dyn ShapeBorder> = Box::new(inset_painting::RoundedRectangleBorder::new(
8821 inset_painting::BorderSide::NONE,
8822 inset_painting::BorderRadiusGeometry::circular(10.0),
8823 ));
8824 let clipper = ShapeBorderClipper::new(square.clone_box(), Some(TextDirection::Ltr));
8825 let clip = clipper.get_clip(Size::new(40.0, 40.0));
8826 assert!(clip.contains(Point::new(20.0, 20.0), FillRule::NonZero));
8827 assert!(
8828 !clip.contains(Point::new(0.5, 0.5), FillRule::NonZero),
8829 "a rounded corner"
8830 );
8831 let same = ShapeBorderClipper::new(square.clone_box(), Some(TextDirection::Ltr));
8832 assert!(!clipper.should_reclip(&same));
8833 let other = ShapeBorderClipper::new(square, Some(TextDirection::Rtl));
8834 assert!(clipper.should_reclip(&other));
8835 }
8836}