glycin_common/
memory_format_selection.rs

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