Skip to main content

glycin_common/
memory_format_selection.rs

1use std::borrow::Borrow;
2
3use crate::{MemoryFormat, MemoryFormatInfo};
4
5/// Selection of memory formats the API user accepts
6#[cfg(feature = "gobject")]
7#[glib::flags(name = "GlyMemoryFormatSelection")]
8pub enum MemoryFormatSelection {
9    B8g8r8a8Premultiplied = (1 << 0),
10    A8r8g8b8Premultiplied = (1 << 1),
11    R8g8b8a8Premultiplied = (1 << 2),
12    B8g8r8a8 = (1 << 3),
13    A8r8g8b8 = (1 << 4),
14    R8g8b8a8 = (1 << 5),
15    A8b8g8r8 = (1 << 6),
16    R8g8b8 = (1 << 7),
17    B8g8r8 = (1 << 8),
18    R16g16b16 = (1 << 9),
19    R16g16b16a16Premultiplied = (1 << 10),
20    R16g16b16a16 = (1 << 11),
21    R16g16b16Float = (1 << 12),
22    R16g16b16a16Float = (1 << 13),
23    R32g32b32Float = (1 << 14),
24    R32g32b32a32FloatPremultiplied = (1 << 15),
25    R32g32b32a32Float = (1 << 16),
26    G8a8Premultiplied = (1 << 17),
27    G8a8 = (1 << 18),
28    G8 = (1 << 19),
29    G16a16Premultiplied = (1 << 20),
30    G16a16 = (1 << 21),
31    G16 = (1 << 22),
32}
33
34#[cfg(not(feature = "gobject"))]
35bitflags::bitflags! {
36    /// Selection of memory formats the API user accepts
37    #[derive(Debug, Clone, Copy)]
38    pub struct MemoryFormatSelection: u32 {
39        const B8g8r8a8Premultiplied = (1 << 0);
40        const A8r8g8b8Premultiplied = (1 << 1);
41        const R8g8b8a8Premultiplied = (1 << 2);
42        const B8g8r8a8 = (1 << 3);
43        const A8r8g8b8 = (1 << 4);
44        const R8g8b8a8 = (1 << 5);
45        const A8b8g8r8 = (1 << 6);
46        const R8g8b8 = (1 << 7);
47        const B8g8r8 = (1 << 8);
48        const R16g16b16 = (1 << 9);
49        const R16g16b16a16Premultiplied = (1 << 10);
50        const R16g16b16a16 = (1 << 11);
51        const R16g16b16Float = (1 << 12);
52        const R16g16b16a16Float = (1 << 13);
53        const R32g32b32Float = (1 << 14);
54        const R32g32b32a32FloatPremultiplied = (1 << 15);
55        const R32g32b32a32Float = (1 << 16);
56        const G8a8Premultiplied = (1 << 17);
57        const G8a8 = (1 << 18);
58        const G8 = (1 << 19);
59        const G16a16Premultiplied = (1 << 20);
60        const G16a16 = (1 << 21);
61        const G16 = (1 << 22);
62    }
63}
64
65impl Default for MemoryFormatSelection {
66    fn default() -> Self {
67        Self::all()
68    }
69}
70
71impl MemoryFormatSelection {
72    const X: [(MemoryFormatSelection, MemoryFormat); 23] = [
73        (
74            MemoryFormatSelection::B8g8r8a8Premultiplied,
75            MemoryFormat::B8g8r8a8Premultiplied,
76        ),
77        (
78            MemoryFormatSelection::A8r8g8b8Premultiplied,
79            MemoryFormat::A8r8g8b8Premultiplied,
80        ),
81        (
82            MemoryFormatSelection::R8g8b8a8Premultiplied,
83            MemoryFormat::R8g8b8a8Premultiplied,
84        ),
85        (MemoryFormatSelection::B8g8r8a8, MemoryFormat::B8g8r8a8),
86        (MemoryFormatSelection::A8r8g8b8, MemoryFormat::A8r8g8b8),
87        (MemoryFormatSelection::R8g8b8a8, MemoryFormat::R8g8b8a8),
88        (MemoryFormatSelection::A8b8g8r8, MemoryFormat::A8b8g8r8),
89        (MemoryFormatSelection::R8g8b8, MemoryFormat::R8g8b8),
90        (MemoryFormatSelection::B8g8r8, MemoryFormat::B8g8r8),
91        (MemoryFormatSelection::R16g16b16, MemoryFormat::R16g16b16),
92        (
93            MemoryFormatSelection::R16g16b16a16Premultiplied,
94            MemoryFormat::R16g16b16a16Premultiplied,
95        ),
96        (
97            MemoryFormatSelection::R16g16b16a16,
98            MemoryFormat::R16g16b16a16,
99        ),
100        (
101            MemoryFormatSelection::R16g16b16Float,
102            MemoryFormat::R16g16b16Float,
103        ),
104        (
105            MemoryFormatSelection::R16g16b16a16Float,
106            MemoryFormat::R16g16b16a16Float,
107        ),
108        (
109            MemoryFormatSelection::R32g32b32Float,
110            MemoryFormat::R32g32b32Float,
111        ),
112        (
113            MemoryFormatSelection::R32g32b32a32FloatPremultiplied,
114            MemoryFormat::R32g32b32a32FloatPremultiplied,
115        ),
116        (
117            MemoryFormatSelection::R32g32b32a32Float,
118            MemoryFormat::R32g32b32a32Float,
119        ),
120        (
121            MemoryFormatSelection::G8a8Premultiplied,
122            MemoryFormat::G8a8Premultiplied,
123        ),
124        (MemoryFormatSelection::G8a8, MemoryFormat::G8a8),
125        (MemoryFormatSelection::G8, MemoryFormat::G8),
126        (
127            MemoryFormatSelection::G16a16Premultiplied,
128            MemoryFormat::G16a16Premultiplied,
129        ),
130        (MemoryFormatSelection::G16a16, MemoryFormat::G16a16),
131        (MemoryFormatSelection::G16, MemoryFormat::G16),
132    ];
133
134    /// List of selected memory formats
135    pub fn memory_formats(self) -> Vec<MemoryFormat> {
136        let mut vec = Vec::new();
137        for (selection, format) in Self::X {
138            if self.contains(selection) {
139                vec.push(format);
140            }
141        }
142
143        vec
144    }
145    pub fn from_memory_format(memory_format: MemoryFormat) -> Self {
146        for (selection, format) in Self::X {
147            if format == memory_format {
148                return selection;
149            }
150        }
151
152        Self::empty()
153    }
154
155    pub fn from_memory_formats(
156        memory_formats: impl IntoIterator<Item = impl Borrow<MemoryFormat>>,
157    ) -> Self {
158        let mut x = Self::empty();
159        for format in memory_formats {
160            x |= Self::from_memory_format(*format.borrow());
161        }
162        x
163    }
164
165    /// Select the best contained format to represent `src`
166    ///
167    /// The function returns `None` if no formats are selected.
168    ///
169    /// ```
170    /// # use glycin_common::{MemoryFormatSelection, MemoryFormat};
171    ///
172    /// assert_eq!(
173    ///     (MemoryFormatSelection::R8g8b8 | MemoryFormatSelection::R8g8b8a8)
174    ///         .best_format_for(MemoryFormat::A8b8g8r8),
175    ///     Some(MemoryFormat::R8g8b8a8)
176    /// );
177    ///
178    /// assert_eq!(
179    ///     (MemoryFormatSelection::R8g8b8 | MemoryFormatSelection::R8g8b8a8)
180    ///         .best_format_for(MemoryFormat::B8g8r8),
181    ///     Some(MemoryFormat::R8g8b8)
182    /// );
183    ///
184    /// assert_eq!(
185    ///     (MemoryFormatSelection::R8g8b8 | MemoryFormatSelection::R16g16b16)
186    ///         .best_format_for(MemoryFormat::B8g8r8),
187    ///     Some(MemoryFormat::R8g8b8)
188    /// );
189    ///
190    /// assert_eq!(
191    ///     (MemoryFormatSelection::R8g8b8 | MemoryFormatSelection::R16g16b16)
192    ///         .best_format_for(MemoryFormat::R16g16b16Float),
193    ///     Some(MemoryFormat::R16g16b16)
194    /// );
195    ///
196    /// assert_eq!(
197    ///     MemoryFormatSelection::empty().best_format_for(MemoryFormat::R16g16b16Float),
198    ///     None
199    /// );
200    /// ```
201    pub fn best_format_for(self, src: MemoryFormat) -> Option<MemoryFormat> {
202        let formats: Vec<MemoryFormat> = self.memory_formats();
203
204        // Shortcut if format itself is supported
205        if formats.contains(&src) {
206            return Some(src);
207        }
208
209        let mut formats_categorized = formats
210            .into_iter()
211            .map(|x| {
212                (
213                    // Prioritize formats by how good they can represent the original format
214                    (
215                        x.has_alpha() == src.has_alpha(),
216                        x.n_channels() >= src.n_channels(),
217                        x.channel_type() == src.channel_type(),
218                        x.channel_type().size() >= src.channel_type().size(),
219                        // Don't have unnecessary many channels
220                        -(x.n_channels() as i16),
221                        // Don't have unnecessary large types
222                        -(x.channel_type().size() as i16),
223                    ),
224                    x,
225                )
226            })
227            .collect::<Vec<_>>();
228
229        formats_categorized.sort_by_key(|x| x.0);
230
231        // The best format is the highest ranked, i.e. the last one
232        formats_categorized.last().map(|x| x.1)
233    }
234}