1#[derive(Clone, Copy, Debug, Default)]
7pub struct Unorm;
8
9#[derive(Clone, Copy, Debug, Default)]
11pub struct Inorm;
12
13#[derive(Clone, Copy, Debug, Default)]
15pub struct Uint;
16
17#[derive(Clone, Copy, Debug, Default)]
19pub struct Int;
20
21#[derive(Clone, Copy, Debug, Default)]
23pub struct Uscaled;
24
25#[derive(Clone, Copy, Debug, Default)]
27pub struct Iscaled;
28
29#[derive(Clone, Copy, Debug, Default)]
31pub struct Srgb;
32
33#[derive(Clone, Copy, Debug, Default)]
35pub struct Float;
36
37#[derive(Clone, Copy, Debug, Default)]
39pub struct _8;
40
41#[derive(Clone, Copy, Debug, Default)]
43pub struct _16;
44
45#[derive(Clone, Copy, Debug, Default)]
47pub struct _32;
48
49#[derive(Clone, Copy, Debug, Default)]
51pub struct _64;
52
53pub trait ChannelSize {
56 const SIZE: u32;
58}
59
60impl ChannelSize for _8 {
61 const SIZE: u32 = 1;
62}
63impl ChannelSize for _16 {
64 const SIZE: u32 = 2;
65}
66impl ChannelSize for _32 {
67 const SIZE: u32 = 4;
68}
69impl ChannelSize for _64 {
70 const SIZE: u32 = 8;
71}
72
73pub trait ChannelRepr<S> {
75 type Repr: Sized + std::fmt::Debug + Default + Copy + Send + Sync + 'static;
77}
78
79macro_rules! impl_channel_repr {
81 ($($type:ident * $size:ident = $repr:ident;)*) => {
82 $(
83 impl ChannelRepr<$size> for $type { type Repr = $repr; }
84 )*
85 };
86}
87
88impl_channel_repr! {
90 Unorm * _8 = u8;
91 Inorm * _8 = u8;
92 Uint * _8 = u8;
93 Int * _8 = u8;
94 Uscaled * _8 = u8;
95 Iscaled * _8 = u8;
96 Srgb * _8 = u8;
97
98 Unorm * _16 = u16;
99 Inorm * _16 = u16;
100 Uint * _16 = u16;
101 Int * _16 = u16;
102 Uscaled * _16 = u16;
103 Iscaled * _16 = u16;
104 Srgb * _16 = u16;
105
106 Unorm * _32 = u32;
107 Inorm * _32 = u32;
108 Uint * _32 = u32;
109 Int * _32 = u32;
110 Uscaled * _32 = u32;
111 Iscaled * _32 = u32;
112 Srgb * _32 = u32;
113 Float * _32 = f32;
114
115 Unorm * _64 = u64;
116 Inorm * _64 = u64;
117 Uint * _64 = u64;
118 Int * _64 = u64;
119 Uscaled * _64 = u64;
120 Iscaled * _64 = u64;
121 Srgb * _64 = u64;
122 Float * _64 = f64;
123}
124
125#[derive(Clone, Copy, Debug, Default)]
127pub struct R;
128
129#[derive(Clone, Copy, Debug, Default)]
131pub struct Rg;
132
133#[derive(Clone, Copy, Debug, Default)]
135pub struct Rgb;
136
137#[derive(Clone, Copy, Debug, Default)]
139pub struct Rgba;
140
141#[derive(Clone, Copy, Debug, Default)]
143pub struct Bgr;
144
145#[derive(Clone, Copy, Debug, Default)]
147pub struct Bgra;
148
149#[derive(Clone, Copy, Debug, Default)]
151pub struct Abgr;
152
153pub trait PixelRepr<S, T> {
155 type Repr: Sized + std::fmt::Debug + Default + Copy + Send + Sync + 'static;
157}
158
159macro_rules! num_channels {
161 (R) => {
162 1
163 };
164 (Rg) => {
165 2
166 };
167 (Rgb) => {
168 3
169 };
170 (Rgba) => {
171 4
172 };
173 (Bgr) => {
174 3
175 };
176 (Bgra) => {
177 4
178 };
179 (Abgr) => {
180 4
181 };
182}
183
184macro_rules! impl_pixel_repr {
186 ($($channels:ident;)*) => {
187 $(
188 impl<S, T> PixelRepr<S, T> for $channels
189 where
190 S: ChannelSize,
191 T: ChannelRepr<S>,
192 {
193 type Repr = [<T as ChannelRepr<S>>::Repr; num_channels!($channels)];
194 }
195 )*
196 };
197}
198
199impl_pixel_repr! {
201 R;
202 Rg;
203 Rgb;
204 Rgba;
205 Bgr;
206 Bgra;
207 Abgr;
208}
209
210#[repr(transparent)]
212pub struct Pixel<C, S, T>
213where
214 C: PixelRepr<S, T>,
215{
216 pub repr: <C as PixelRepr<S, T>>::Repr,
218}
219
220impl<C, S, T> Copy for Pixel<C, S, T> where C: PixelRepr<S, T> {}
221
222impl<C, S, T> Clone for Pixel<C, S, T>
223where
224 C: PixelRepr<S, T>,
225{
226 fn clone(&self) -> Self {
227 Pixel {
228 repr: self.repr.clone(),
229 }
230 }
231}
232
233impl<C, S, T> std::fmt::Debug for Pixel<C, S, T>
234where
235 C: PixelRepr<S, T>,
236{
237 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 fmt.debug_struct("Pixel").field("repr", &self.repr).finish()
239 }
240}
241
242impl<C, S, T> Default for Pixel<C, S, T>
243where
244 C: PixelRepr<S, T>,
245{
246 fn default() -> Self {
247 Pixel {
248 repr: C::Repr::default(),
249 }
250 }
251}
252
253pub trait AsPixel: Copy + std::fmt::Debug + Default + Send + Sync + 'static {
259 const NAME: &'static str;
261
262 const SIZE: u32;
264
265 const FORMAT: rendy_core::hal::format::Format;
267}
268
269macro_rules! impl_pixel {
270 ($($alias:ident = $channels:ident $size:ident $type:ident;)*) => {
271 $(
272 pub type $alias = Pixel<$channels, $size, $type>;
274
275 impl AsPixel for $alias {
276 const NAME: &'static str = stringify!($alias);
277 const SIZE: u32 = num_channels!($channels) * <$size as ChannelSize>::SIZE;
278 const FORMAT: rendy_core::hal::format::Format = rendy_core::hal::format::Format::$alias;
279 }
280 )*
281 };
282}
283
284impl_pixel! {
287 R8Unorm = R _8 Unorm;
288 R8Snorm = R _8 Inorm;
289 R8Uscaled = R _8 Uscaled;
290 R8Sscaled = R _8 Iscaled;
291 R8Uint = R _8 Uint;
292 R8Sint = R _8 Int;
293 R8Srgb = R _8 Srgb;
294 Rg8Unorm = Rg _8 Unorm;
295 Rg8Snorm = Rg _8 Inorm;
296 Rg8Uscaled = Rg _8 Uscaled;
297 Rg8Sscaled = Rg _8 Iscaled;
298 Rg8Uint = Rg _8 Uint;
299 Rg8Sint = Rg _8 Int;
300 Rg8Srgb = Rg _8 Srgb;
301 Rgb8Unorm = Rgb _8 Unorm;
302 Rgb8Snorm = Rgb _8 Inorm;
303 Rgb8Uscaled = Rgb _8 Uscaled;
304 Rgb8Sscaled = Rgb _8 Iscaled;
305 Rgb8Uint = Rgb _8 Uint;
306 Rgb8Sint = Rgb _8 Int;
307 Rgb8Srgb = Rgb _8 Srgb;
308 Bgr8Unorm = Bgr _8 Unorm;
309 Bgr8Snorm = Bgr _8 Inorm;
310 Bgr8Uscaled = Bgr _8 Uscaled;
311 Bgr8Sscaled = Bgr _8 Iscaled;
312 Bgr8Uint = Bgr _8 Uint;
313 Bgr8Sint = Bgr _8 Int;
314 Bgr8Srgb = Bgr _8 Srgb;
315 Rgba8Unorm = Rgba _8 Unorm;
316 Rgba8Snorm = Rgba _8 Inorm;
317 Rgba8Uscaled = Rgba _8 Uscaled;
318 Rgba8Sscaled = Rgba _8 Iscaled;
319 Rgba8Uint = Rgba _8 Uint;
320 Rgba8Sint = Rgba _8 Int;
321 Rgba8Srgb = Rgba _8 Srgb;
322 Bgra8Unorm = Bgra _8 Unorm;
323 Bgra8Snorm = Bgra _8 Inorm;
324 Bgra8Uscaled = Bgra _8 Uscaled;
325 Bgra8Sscaled = Bgra _8 Iscaled;
326 Bgra8Uint = Bgra _8 Uint;
327 Bgra8Sint = Bgra _8 Int;
328 Bgra8Srgb = Bgra _8 Srgb;
329 Abgr8Unorm = Abgr _8 Unorm;
330 Abgr8Snorm = Abgr _8 Inorm;
331 Abgr8Uscaled = Abgr _8 Uscaled;
332 Abgr8Sscaled = Abgr _8 Iscaled;
333 Abgr8Uint = Abgr _8 Uint;
334 Abgr8Sint = Abgr _8 Int;
335 Abgr8Srgb = Abgr _8 Srgb;
336 R16Unorm = R _16 Unorm;
337 R16Snorm = R _16 Inorm;
338 R16Uscaled = R _16 Uscaled;
339 R16Sscaled = R _16 Iscaled;
340 R16Uint = R _16 Uint;
341 R16Sint = R _16 Int;
342 Rg16Unorm = Rg _16 Unorm;
344 Rg16Snorm = Rg _16 Inorm;
345 Rg16Uscaled = Rg _16 Uscaled;
346 Rg16Sscaled = Rg _16 Iscaled;
347 Rg16Uint = Rg _16 Uint;
348 Rg16Sint = Rg _16 Int;
349 Rgb16Unorm = Rgb _16 Unorm;
351 Rgb16Snorm = Rgb _16 Inorm;
352 Rgb16Uscaled = Rgb _16 Uscaled;
353 Rgb16Sscaled = Rgb _16 Iscaled;
354 Rgb16Uint = Rgb _16 Uint;
355 Rgb16Sint = Rgb _16 Int;
356 Rgba16Unorm = Rgba _16 Unorm;
358 Rgba16Snorm = Rgba _16 Inorm;
359 Rgba16Uscaled = Rgba _16 Uscaled;
360 Rgba16Sscaled = Rgba _16 Iscaled;
361 Rgba16Uint = Rgba _16 Uint;
362 Rgba16Sint = Rgba _16 Int;
363 R32Uint = R _32 Uint;
365 R32Sint = R _32 Int;
366 R32Sfloat = R _32 Float;
367 Rg32Uint = Rg _32 Uint;
368 Rg32Sint = Rg _32 Int;
369 Rg32Sfloat = Rg _32 Float;
370 Rgb32Uint = Rgb _32 Uint;
371 Rgb32Sint = Rgb _32 Int;
372 Rgb32Sfloat = Rgb _32 Float;
373 Rgba32Uint = Rgba _32 Uint;
374 Rgba32Sint = Rgba _32 Int;
375 Rgba32Sfloat = Rgba _32 Float;
376 R64Uint = R _64 Uint;
377 R64Sint = R _64 Int;
378 R64Sfloat = R _64 Float;
379 Rg64Uint = Rg _64 Uint;
380 Rg64Sint = Rg _64 Int;
381 Rg64Sfloat = Rg _64 Float;
382 Rgb64Uint = Rgb _64 Uint;
383 Rgb64Sint = Rgb _64 Int;
384 Rgb64Sfloat = Rgb _64 Float;
385 Rgba64Uint = Rgba _64 Uint;
386 Rgba64Sint = Rgba _64 Int;
387 Rgba64Sfloat = Rgba _64 Float;
388}
389
390#[cfg(feature = "palette")]
391mod palette_pixel {
392 use palette::{
396 encoding,
397 luma::{Luma, LumaStandard, Lumaa},
398 rgb::{Rgb, RgbStandard, Rgba},
399 white_point::D65,
400 Component,
401 };
402
403 macro_rules! impl_from_palette {
404 (# $color:ident R as $encoding:path) => {
405 {
406 let f = $color.into_format();
407 let _: (f32,) = f.into_components();
408 let (r,) = f.into_encoding::<$encoding>().into_format().into_components();
409 Self { repr: [r] }
410 }
411 };
412 (# $color:ident Rg as $encoding:path) => {
413 {
414 let f = $color.into_format();
415 let _: (f32,f32) = f.into_components();
416 let (r,g) = f.into_encoding::<$encoding>().into_format().into_components();
417 Self { repr: [r,g] }
418 }
419 };
420 (# $color:ident Rgb as $encoding:path) => {
421 {
422 let f = $color.into_format();
423 let _: (f32,f32,f32) = f.into_components();
424 let (r,g,b) = f.into_encoding::<$encoding>().into_format().into_components();
425 Self { repr: [r,g,b] }
426 }
427 };
428 (# $color:ident Rgba as $encoding:path) => {
429 {
430 let f = $color.into_format();
431 let _: (f32,f32,f32,f32) = f.into_components();
432 let (r,g,b,a) = f.into_encoding::<$encoding>().into_format().into_components();
433 Self { repr: [r,g,b,a] }
434 }
435 };
436
437 ($($container:path as $encoding:path : $standard:path => $channels:ident $($repr:ident)|+),* $(,)*) => {$($(
438 impl<S, T, B> From<$container> for super::Pixel<super::$channels, B, super::$repr>
439 where
440 S: $standard,
441 T: Component,
442 B: super::ChannelSize,
443 super::$repr: super::ChannelRepr<B>,
444 <super::$repr as super::ChannelRepr<B>>::Repr: Component,
445 {
446 fn from(color: $container) -> Self {
447 impl_from_palette!(# color $channels as $encoding)
448 }
449 }
450 )+)*};
451 }
452
453 impl_from_palette! {
454 Rgb<S, T> as encoding::Srgb: RgbStandard<Space = encoding::Srgb> => Rgb Srgb,
455 Rgba<S, T> as encoding::Srgb: RgbStandard<Space = encoding::Srgb> => Rgba Srgb,
456 Luma<S, T> as encoding::Srgb: LumaStandard<WhitePoint = D65> => R Srgb,
457 Lumaa<S, T> as encoding::Srgb: LumaStandard<WhitePoint = D65> => Rg Srgb,
458
459 Rgb<S, T> as encoding::Linear<encoding::Srgb>: RgbStandard<Space = encoding::Srgb> => Rgb Unorm | Float,
460 Rgba<S, T> as encoding::Linear<encoding::Srgb>: RgbStandard<Space = encoding::Srgb> => Rgba Unorm | Float,
461
462 Luma<S, T> as encoding::Linear<D65>: LumaStandard<WhitePoint = D65> => R Unorm | Float,
463 Lumaa<S, T> as encoding::Linear<D65>: LumaStandard<WhitePoint = D65> => Rg Unorm | Float,
464 }
465}