1use std::collections::BTreeMap;
2use std::os::fd::AsRawFd;
3use std::time::Duration;
4
5use glycin_common::{BinaryData, MemoryFormat, MemoryFormatInfo};
6use gufo_common::orientation::Orientation;
7use memmap::MmapMut;
8use serde::{Deserialize, Serialize};
9use zbus::zvariant::as_value::{self, optional};
10use zbus::zvariant::{self, DeserializeDict, Optional, SerializeDict, Type};
11
12use crate::ImgBuf;
13use crate::error::DimensionTooLargerError;
14use crate::safe_math::{SafeConversion, SafeMath};
15
16#[derive(Deserialize, Serialize, Type, Debug)]
17pub struct InitRequest {
18 pub fd: zvariant::OwnedFd,
20 pub mime_type: String,
21 pub details: InitializationDetails,
22}
23
24#[derive(DeserializeDict, SerializeDict, Type, Debug, Default)]
25#[zvariant(signature = "dict")]
26#[non_exhaustive]
27pub struct InitializationDetails {
28 pub base_dir: Option<std::path::PathBuf>,
29}
30
31const fn true_const() -> bool {
32 true
33}
34
35#[derive(Deserialize, Serialize, Type, Debug, Clone, Default)]
36#[zvariant(signature = "dict")]
37#[non_exhaustive]
38pub struct FrameRequest {
39 #[serde(with = "optional", skip_serializing_if = "Option::is_none", default)]
41 pub scale: Option<(u32, u32)>,
42 #[serde(with = "optional", skip_serializing_if = "Option::is_none", default)]
44 pub clip: Option<(u32, u32, u32, u32)>,
45 #[serde(with = "as_value", default = "true_const")]
47 pub loop_animation: bool,
48}
49
50#[derive(Deserialize, Serialize, Type, Debug, Clone)]
54pub struct RemoteImage {
55 pub frame_request: zvariant::OwnedObjectPath,
56 pub details: ImageDetails,
57}
58
59impl RemoteImage {
60 pub fn new(details: ImageDetails, frame_request: zvariant::OwnedObjectPath) -> Self {
61 Self {
62 frame_request,
63 details,
64 }
65 }
66}
67
68#[derive(DeserializeDict, SerializeDict, Type, Debug, Clone, Default)]
69#[zvariant(signature = "dict")]
70#[non_exhaustive]
71pub struct ImageDetails {
72 pub width: u32,
78 pub height: u32,
79 pub dimensions_inch: Option<(f64, f64)>,
81 pub info_format_name: Option<String>,
82 pub info_dimensions_text: Option<String>,
84 pub metadata_exif: Option<BinaryData>,
85 pub metadata_xmp: Option<BinaryData>,
86 pub metadata_key_value: Option<BTreeMap<String, String>>,
87 pub transformation_ignore_exif: bool,
88 pub transformation_orientation: Option<Orientation>,
90}
91
92impl ImageDetails {
93 pub fn new(width: u32, height: u32) -> Self {
94 Self {
95 width,
96 height,
97 dimensions_inch: None,
98 info_dimensions_text: None,
99 info_format_name: None,
100 metadata_exif: None,
101 metadata_xmp: None,
102 metadata_key_value: None,
103 transformation_ignore_exif: false,
104 transformation_orientation: None,
105 }
106 }
107}
108
109#[derive(Deserialize, Serialize, Type, Debug)]
110pub struct Frame {
111 pub width: u32,
112 pub height: u32,
113 pub stride: u32,
115 pub memory_format: MemoryFormat,
116 pub texture: BinaryData,
117 pub delay: Optional<Duration>,
121 pub details: FrameDetails,
122}
123
124impl Frame {
125 pub fn n_bytes(&self) -> Result<usize, DimensionTooLargerError> {
126 self.stride.try_usize()?.smul(self.height.try_usize()?)
127 }
128}
129
130#[derive(DeserializeDict, SerializeDict, Type, Debug, Default, Clone)]
131#[zvariant(signature = "dict")]
132#[non_exhaustive]
133pub struct FrameDetails {
135 pub color_icc_profile: Option<BinaryData>,
137 pub color_cicp: Option<[u8; 4]>,
139 pub info_bit_depth: Option<u8>,
143 pub info_alpha_channel: Option<bool>,
147 pub info_grayscale: Option<bool>,
151 pub n_frame: Option<u64>,
152}
153
154impl Frame {
155 pub fn new(
156 width: u32,
157 height: u32,
158 memory_format: MemoryFormat,
159 texture: BinaryData,
160 ) -> Result<Self, DimensionTooLargerError> {
161 let stride = memory_format
162 .n_bytes()
163 .u32()
164 .checked_mul(width)
165 .ok_or(DimensionTooLargerError)?;
166
167 Ok(Self {
168 width,
169 height,
170 stride,
171 memory_format,
172 texture,
173 delay: None.into(),
174 details: Default::default(),
175 })
176 }
177}
178
179impl Frame {
180 pub fn as_img_buf(&self) -> std::io::Result<ImgBuf> {
181 let raw_fd = self.texture.as_raw_fd();
182 let original_mmap = unsafe { MmapMut::map_mut(raw_fd) }?;
183
184 Ok(ImgBuf::MMap {
185 mmap: original_mmap,
186 raw_fd,
187 })
188 }
189}
190
191#[derive(Deserialize, Serialize, Type, Debug, Clone)]
193pub struct RemoteEditableImage {
194 pub edit_request: zvariant::OwnedObjectPath,
195}
196
197impl RemoteEditableImage {
198 pub fn new(frame_request: zvariant::OwnedObjectPath) -> Self {
199 Self {
200 edit_request: frame_request,
201 }
202 }
203}
204
205#[derive(DeserializeDict, SerializeDict, Type, Debug)]
206#[zvariant(signature = "dict")]
207#[non_exhaustive]
208pub struct NewImage {
209 pub image_info: ImageDetails,
210 pub frames: Vec<Frame>,
211}
212
213impl NewImage {
214 pub fn new(image_info: ImageDetails, frames: Vec<Frame>) -> Self {
215 Self { image_info, frames }
216 }
217}
218
219#[derive(DeserializeDict, SerializeDict, Type, Debug, Default)]
220#[zvariant(signature = "dict")]
221#[non_exhaustive]
222pub struct EncodingOptions {
223 pub quality: Option<u8>,
224 pub compression: Option<u8>,
225}
226
227#[derive(DeserializeDict, SerializeDict, Type, Debug)]
228#[zvariant(signature = "dict")]
229#[non_exhaustive]
230pub struct EncodedImage {
231 pub data: BinaryData,
232}
233
234impl EncodedImage {
235 pub fn new(data: BinaryData) -> Self {
236 Self { data }
237 }
238}