use crate::{ App, Bounds, Element, ElementId, GlobalElementId, IntoElement, LayoutId, ObjectFit, Pixels, Style, StyleRefinement, Styled, Window, }; #[cfg(target_os = "macos")] use media::core_video::CVImageBuffer; use refineable::Refineable; /// A source of a surface's content. #[derive(Clone, Debug, PartialEq, Eq)] pub enum SurfaceSource { /// A macOS image buffer from CoreVideo #[cfg(target_os = "macos")] Surface(CVImageBuffer), } #[cfg(target_os = "macos")] impl From for SurfaceSource { fn from(value: CVImageBuffer) -> Self { SurfaceSource::Surface(value) } } /// A surface element. pub struct Surface { source: SurfaceSource, object_fit: ObjectFit, style: StyleRefinement, } /// Create a new surface element. pub fn surface(source: impl Into) -> Surface { Surface { source: source.into(), object_fit: ObjectFit::Contain, style: Default::default(), } } impl Surface { /// Set the object fit for the image. pub fn object_fit(mut self, object_fit: ObjectFit) -> Self { self.object_fit = object_fit; self } } impl Element for Surface { type RequestLayoutState = (); type PrepaintState = (); fn id(&self) -> Option { None } fn request_layout( &mut self, _global_id: Option<&GlobalElementId>, window: &mut Window, cx: &mut App, ) -> (LayoutId, Self::RequestLayoutState) { let mut style = Style::default(); style.refine(&self.style); let layout_id = window.request_layout(style, [], cx); (layout_id, ()) } fn prepaint( &mut self, _global_id: Option<&GlobalElementId>, _bounds: Bounds, _request_layout: &mut Self::RequestLayoutState, _window: &mut Window, _cx: &mut App, ) -> Self::PrepaintState { } fn paint( &mut self, _global_id: Option<&GlobalElementId>, #[cfg_attr(not(target_os = "macos"), allow(unused_variables))] bounds: Bounds, _: &mut Self::RequestLayoutState, _: &mut Self::PrepaintState, #[cfg_attr(not(target_os = "macos"), allow(unused_variables))] window: &mut Window, _: &mut App, ) { match &self.source { #[cfg(target_os = "macos")] SurfaceSource::Surface(surface) => { let size = crate::size(surface.width().into(), surface.height().into()); let new_bounds = self.object_fit.get_bounds(bounds, size); // TODO: Add support for corner_radii window.paint_surface(new_bounds, surface.clone()); } #[allow(unreachable_patterns)] _ => {} } } } impl IntoElement for Surface { type Element = Self; fn into_element(self) -> Self::Element { self } } impl Styled for Surface { fn style(&mut self) -> &mut StyleRefinement { &mut self.style } }