use std::sync::{Mutex, OnceLock};
use gio::glib;
use glib::prelude::*;
use glib::subclass::prelude::*;
use glycin_utils::MemoryFormat;
use gufo_common::physical_dimension::PixelDensity;
use super::init;
use crate::gobject::GlyPixelDensity;
static_assertions::assert_impl_all!(GlyNewFrame: Send, Sync);
#[derive(Debug, Copy, Clone, gio::glib::Enum, Default)]
#[enum_type(name = "GlyPhysicalDimensionUnit")]
#[repr(i32)]
#[non_exhaustive]
pub enum GlyPhysicalDimensionUnit {
#[default]
Inch = 1,
Pica = 2,
Point = 3,
Meter = 4,
Centimeter = 5,
Millimeter = 6,
}
pub mod imp {
use super::*;
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::GlyNewFrame)]
pub struct GlyNewFrame {
#[property(get, construct_only)]
width: OnceLock<u32>,
#[property(get, construct_only)]
height: OnceLock<u32>,
#[property(get, construct_only)]
stride: OnceLock<u32>,
#[property(get, construct_only, builder(MemoryFormat::R8g8b8))]
memory_format: OnceLock<MemoryFormat>,
#[property(get, construct_only)]
texture: OnceLock<glib::Bytes>,
#[property(get, set, nullable)]
color_icc_profile: Mutex<Option<glib::Bytes>>,
pub(crate) pixel_density: Mutex<Option<PixelDensity>>,
}
#[glib::object_subclass]
impl ObjectSubclass for GlyNewFrame {
const NAME: &'static str = "GlyNewFrame";
type Type = super::GlyNewFrame;
}
#[glib::derived_properties]
impl ObjectImpl for GlyNewFrame {
fn constructed(&self) {
self.parent_constructed();
init();
}
}
}
glib::wrapper! {
pub struct GlyNewFrame(ObjectSubclass<imp::GlyNewFrame>);
}
impl GlyNewFrame {
pub fn new(
width: u32,
height: u32,
stride: Option<u32>,
memory_format: MemoryFormat,
texture: glib::Bytes,
) -> Self {
glib::Object::builder()
.property("width", width)
.property("height", height)
.property("stride", stride.unwrap_or_default())
.property("memory-format", memory_format)
.property("texture", texture)
.build()
}
pub fn set_pixel_density(&self, pixel_density: Option<GlyPixelDensity>) {
*self.imp().pixel_density.lock().unwrap() =
pixel_density.map(|x| x.inner().to_owned().unwrap());
}
pub async fn build(&self, creator: &mut crate::Creator) -> Result<(), crate::Error> {
let frame = if self.stride() == 0 {
creator.add_frame(
self.width(),
self.height(),
self.memory_format(),
self.texture().into_data().to_vec(),
)?
} else {
creator.add_frame_with_stride(
self.width(),
self.height(),
self.stride(),
self.memory_format(),
self.texture().into_data().to_vec(),
)?
};
frame.set_color_icc_profile(self.color_icc_profile().map(|x| x.into_data().to_vec()))?;
frame.set_pixel_density(self.imp().pixel_density.lock().unwrap().clone())?;
Ok(())
}
}