use crate::{ App, Bounds, Element, ElementId, GlobalElementId, IntoElement, LayoutId, ObjectFit, Pixels, Style, StyleRefinement, Styled, Window,};#[cfg(target_os = "macos")]use core_video::pixel_buffer::CVPixelBuffer;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(CVPixelBuffer),} #[cfg(target_os = "macos")]impl From<CVPixelBuffer> for SurfaceSource { fn from(value: CVPixelBuffer) -> 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<SurfaceSource>) -> 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<ElementId> { 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<Pixels>, _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<Pixels>, _: &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.get_width().into(), surface.get_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 }}
use crate::{
App, Bounds, Element, ElementId, GlobalElementId, IntoElement, LayoutId, ObjectFit, Pixels,
Style, StyleRefinement, Styled, Window,
};
#[cfg(target_os = "macos")]
use core_video::pixel_buffer::CVPixelBuffer;
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(CVPixelBuffer),
}
#[cfg(target_os = "macos")]
impl From<CVPixelBuffer> for SurfaceSource {
fn from(value: CVPixelBuffer) -> 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<SurfaceSource>) -> 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<ElementId> {
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<Pixels>,
_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<Pixels>,
_: &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.get_width().into(), surface.get_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
}
}