Skip to main content

glycin_utils/
dbus_types.rs

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    /// Source from which the loader reads the image data
19    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    /// Scale image to these dimensions
40    #[serde(with = "optional", skip_serializing_if = "Option::is_none", default)]
41    pub scale: Option<(u32, u32)>,
42    /// Instruction to only decode part of the image
43    #[serde(with = "optional", skip_serializing_if = "Option::is_none", default)]
44    pub clip: Option<(u32, u32, u32, u32)>,
45    /// Get first frame, if previously selected frame was the last one
46    #[serde(with = "as_value", default = "true_const")]
47    pub loop_animation: bool,
48}
49
50/// Various image metadata
51///
52/// This is returned from the initial `InitRequest` call
53#[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    /// Early dimension information.
73    ///
74    /// This information is often correct. However, it should only be used for
75    /// an early rendering estimates. For everything else, the specific frame
76    /// information should be used.
77    pub width: u32,
78    pub height: u32,
79    /// Image dimensions in inch
80    pub dimensions_inch: Option<(f64, f64)>,
81    pub info_format_name: Option<String>,
82    /// Textual description of the image dimensions
83    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    /// Explicit orientation. If `None` check Exif or XMP.
89    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    /// Line stride
114    pub stride: u32,
115    pub memory_format: MemoryFormat,
116    pub texture: BinaryData,
117    /// Duration to show frame for animations.
118    ///
119    /// If the value is not set, the image is not animated.
120    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]
133/// More information about a frame
134pub struct FrameDetails {
135    /// ICC color profile
136    pub color_icc_profile: Option<BinaryData>,
137    /// Coding-independent code points (HDR information)
138    pub color_cicp: Option<[u8; 4]>,
139    /// Bit depth per channel
140    ///
141    /// Only set if it can differ for the format
142    pub info_bit_depth: Option<u8>,
143    /// Image has alpha channel
144    ///
145    /// Only set if it can differ for the format
146    pub info_alpha_channel: Option<bool>,
147    /// Image uses grayscale mode
148    ///
149    /// Only set if it can differ for the format
150    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/// Editable image
192#[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}