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