1use crate::{
2 App, Bounds, Element, ElementId, GlobalElementId, InspectorElementId, IntoElement, LayoutId,
3 ObjectFit, Pixels, Style, StyleRefinement, Styled, Window,
4};
5#[cfg(any(target_os = "macos", target_os = "ios"))]
6use core_video::pixel_buffer::CVPixelBuffer;
7use refineable::Refineable;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
11pub enum SurfaceSource {
12 #[cfg(any(target_os = "macos", target_os = "ios"))]
14 Surface(CVPixelBuffer),
15}
16
17#[cfg(any(target_os = "macos", target_os = "ios"))]
18impl From<CVPixelBuffer> for SurfaceSource {
19 fn from(value: CVPixelBuffer) -> Self {
20 SurfaceSource::Surface(value)
21 }
22}
23
24pub struct Surface {
26 source: SurfaceSource,
27 object_fit: ObjectFit,
28 style: StyleRefinement,
29}
30
31#[cfg(any(target_os = "macos", target_os = "ios"))]
33pub fn surface(source: impl Into<SurfaceSource>) -> Surface {
34 Surface {
35 source: source.into(),
36 object_fit: ObjectFit::Contain,
37 style: Default::default(),
38 }
39}
40
41impl Surface {
42 pub fn object_fit(mut self, object_fit: ObjectFit) -> Self {
44 self.object_fit = object_fit;
45 self
46 }
47}
48
49impl Element for Surface {
50 type RequestLayoutState = ();
51 type PrepaintState = ();
52
53 fn id(&self) -> Option<ElementId> {
54 None
55 }
56
57 fn source_location(&self) -> Option<&'static core::panic::Location<'static>> {
58 None
59 }
60
61 fn request_layout(
62 &mut self,
63 _global_id: Option<&GlobalElementId>,
64 _inspector_id: Option<&InspectorElementId>,
65 window: &mut Window,
66 cx: &mut App,
67 ) -> (LayoutId, Self::RequestLayoutState) {
68 let mut style = Style::default();
69 style.refine(&self.style);
70 let layout_id = window.request_layout(style, [], cx);
71 (layout_id, ())
72 }
73
74 fn prepaint(
75 &mut self,
76 _global_id: Option<&GlobalElementId>,
77 _inspector_id: Option<&InspectorElementId>,
78 _bounds: Bounds<Pixels>,
79 _request_layout: &mut Self::RequestLayoutState,
80 _window: &mut Window,
81 _cx: &mut App,
82 ) -> Self::PrepaintState {
83 }
84
85 fn paint(
86 &mut self,
87 _global_id: Option<&GlobalElementId>,
88 _inspector_id: Option<&InspectorElementId>,
89 #[cfg_attr(
90 not(any(target_os = "macos", target_os = "ios")),
91 allow(unused_variables)
92 )]
93 bounds: Bounds<Pixels>,
94 _: &mut Self::RequestLayoutState,
95 _: &mut Self::PrepaintState,
96 #[cfg_attr(
97 not(any(target_os = "macos", target_os = "ios")),
98 allow(unused_variables)
99 )]
100 window: &mut Window,
101 _: &mut App,
102 ) {
103 match &self.source {
104 #[cfg(any(target_os = "macos", target_os = "ios"))]
105 SurfaceSource::Surface(surface) => {
106 let size = crate::size(surface.get_width().into(), surface.get_height().into());
107 let new_bounds = self.object_fit.get_bounds(bounds, size);
108 window.paint_surface(new_bounds, surface.clone());
110 }
111 #[allow(unreachable_patterns)]
112 _ => {}
113 }
114 }
115}
116
117impl IntoElement for Surface {
118 type Element = Self;
119
120 fn into_element(self) -> Self::Element {
121 self
122 }
123}
124
125impl Styled for Surface {
126 fn style(&mut self) -> &mut StyleRefinement {
127 &mut self.style
128 }
129}