1use alloc::borrow::ToOwned;
4use alloc::vec::Vec;
5
6use image_texel::image::{
7 AtomicImage, AtomicImageRef, CellImage, CellImageRef, Image, ImageMut, ImageRef,
8};
9use image_texel::texels::U8;
10
11use crate::color::Color;
12use crate::layout::{CanvasLayout, ChannelLayout, LayoutError, PlanarLayout, PlaneBytes, PlaneIdx};
13use crate::shader::Converter;
14
15#[derive(Clone)]
17pub struct Canvas {
18 inner: Image<CanvasLayout>,
19}
20
21#[derive(Clone)]
23pub struct RcCanvas {
24 inner: CellImage<CanvasLayout>,
25}
26
27#[derive(Clone)]
29pub struct ArcCanvas {
30 inner: AtomicImage<CanvasLayout>,
31}
32
33#[derive(Clone)]
35pub struct Plane {
36 inner: Image<PlaneBytes>,
37}
38
39pub struct BytePlaneRef<'data> {
43 pub(crate) inner: ImageRef<'data, PlaneBytes>,
44}
45
46pub struct BytePlaneMut<'data> {
50 pub(crate) inner: ImageMut<'data, PlaneBytes>,
51}
52
53pub struct BytePlaneCells<'data> {
57 pub(crate) inner: CellImageRef<'data, PlaneBytes>,
58}
59
60pub struct BytePlaneAtomics<'data> {
64 pub(crate) inner: AtomicImageRef<'data, PlaneBytes>,
65}
66
67pub struct PlaneRef<'data, T> {
71 pub(crate) inner: ImageRef<'data, PlanarLayout<T>>,
72}
73
74pub struct PlaneMut<'data, T> {
78 pub(crate) inner: ImageMut<'data, PlanarLayout<T>>,
79}
80
81pub struct PlaneCells<'data, T> {
83 pub(crate) inner: CellImageRef<'data, PlanarLayout<T>>,
84}
85
86pub struct PlaneAtomics<'data, T> {
88 pub(crate) inner: AtomicImageRef<'data, PlanarLayout<T>>,
89}
90
91pub struct ChannelsRef<'data, C> {
95 pub(crate) inner: ImageRef<'data, ChannelLayout<C>>,
96}
97
98pub struct ChannelsMut<'data, C> {
102 pub(crate) inner: ImageMut<'data, ChannelLayout<C>>,
103}
104
105impl Canvas {
106 pub fn new(layout: CanvasLayout) -> Self {
124 Canvas {
125 inner: Image::new(layout),
126 }
127 }
128
129 pub fn layout(&self) -> &CanvasLayout {
131 self.inner.layout()
132 }
133
134 pub fn set_layout(&mut self, layout: CanvasLayout) {
136 self.set_layout_conservative(layout);
137 self.inner.as_bytes_mut().fill(0);
138 }
139
140 pub fn set_layout_conservative(&mut self, layout: CanvasLayout) {
142 *self.inner.layout_mut_unguarded() = layout;
143 self.inner.ensure_layout();
144 }
145
146 pub fn as_bytes(&self) -> &[u8] {
150 self.inner.as_bytes()
151 }
152
153 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
168 self.inner.as_bytes_mut()
169 }
170
171 pub fn as_texels<T>(&self, texel: image_texel::Texel<T>) -> &[T] {
173 self.inner.as_texels(texel)
174 }
175
176 pub fn as_texels_mut<T>(&mut self, texel: image_texel::Texel<T>) -> &mut [T] {
178 self.inner.as_mut_texels(texel)
179 }
180
181 pub fn channels_u8(&self) -> Option<ChannelsRef<u8>> {
185 let plane = self.inner.layout().as_plane()?;
186 let layout = plane
187 .as_channel_bytes()?
188 .is_compatible(<u8 as image_texel::AsTexel>::texel())?;
189 Some(ChannelsRef {
190 inner: self.inner.as_ref().with_layout(layout)?,
191 })
192 }
193
194 pub fn channels_u16(&self) -> Option<ChannelsRef<u16>> {
198 let plane = self.inner.layout().as_plane()?;
199 let layout = plane
200 .as_channel_bytes()?
201 .is_compatible(<u16 as image_texel::AsTexel>::texel())?;
202 Some(ChannelsRef {
203 inner: self.inner.as_ref().with_layout(layout)?,
204 })
205 }
206
207 pub fn channels_f32(&self) -> Option<ChannelsRef<f32>> {
211 let plane = self.inner.layout().as_plane()?;
212 let layout = plane
213 .as_channel_bytes()?
214 .is_compatible(<f32 as image_texel::AsTexel>::texel())?;
215 Some(ChannelsRef {
216 inner: self.inner.as_ref().with_layout(layout)?,
217 })
218 }
219
220 pub fn channels_u8_mut(&mut self) -> Option<ChannelsMut<u8>> {
224 let plane = self.inner.layout().as_plane()?;
225 let layout = plane
226 .as_channel_bytes()?
227 .is_compatible(<u8 as image_texel::AsTexel>::texel())?;
228 Some(ChannelsMut {
229 inner: self.inner.as_mut().with_layout(layout)?,
230 })
231 }
232
233 pub fn channels_u16_mut(&mut self) -> Option<ChannelsMut<u16>> {
237 let plane = self.inner.layout().as_plane()?;
238 let layout = plane
239 .as_channel_bytes()?
240 .is_compatible(<u16 as image_texel::AsTexel>::texel())?;
241 Some(ChannelsMut {
242 inner: self.inner.as_mut().with_layout(layout)?,
243 })
244 }
245
246 pub fn channels_f32_mut(&mut self) -> Option<ChannelsMut<f32>> {
250 let plane = self.inner.layout().as_plane()?;
251 let layout = plane
252 .as_channel_bytes()?
253 .is_compatible(<f32 as image_texel::AsTexel>::texel())?;
254 Some(ChannelsMut {
255 inner: self.inner.as_mut().with_layout(layout)?,
256 })
257 }
258
259 pub fn into_bytes(self) -> Vec<u8> {
261 self.as_bytes().to_owned()
263 }
264
265 pub fn plane(&self, idx: u8) -> Option<BytePlaneRef<'_>> {
270 let layout = self.layout().plane(idx)?;
271 Some(BytePlaneRef {
272 inner: self.inner.as_ref().with_layout(layout)?,
273 })
274 }
275
276 pub fn planes<const N: usize>(&self) -> Option<[BytePlaneRef<'_>; N]> {
278 todo!()
279 }
280
281 pub fn plane_mut(&mut self, idx: u8) -> Option<BytePlaneMut<'_>> {
286 let layout = self.layout().plane(idx)?;
287 Some(BytePlaneMut {
288 inner: self.inner.as_mut().with_layout(layout)?,
289 })
290 }
291
292 pub fn planes_mut<const N: usize>(&mut self) -> Option<[BytePlaneMut<'_>; N]> {
297 use image_texel::layout::Bytes;
298
299 let mut layouts = [(); N].map(|()| None);
300
301 for i in 0..N {
302 if i > u8::MAX as usize {
303 return None;
304 }
305
306 layouts[i] = Some(self.layout().plane(i as u8)?);
307 }
308
309 let layouts = layouts.map(|layout| layout.unwrap());
310
311 let mut offset = 0;
312 let frame: ImageMut<'_, Bytes> = self.as_mut().decay();
314
315 let &Bytes(total_len) = frame.layout();
316 let mut frame = frame.with_layout(Bytes(0)).expect("zero-byte layout valid");
317
318 let planes = layouts.map(move |mut layout| {
319 layout.sub_offset(offset);
320 let mut plane = frame
321 .split_layout()
322 .with_layout(layout)
323 .expect("plane layout within frame");
324 let tail = plane.split_layout();
325 let &Bytes(tail_len) = tail.layout();
326 frame = tail.with_layout(Bytes(0)).expect("zero-byte layout valid");
328 offset = total_len - tail_len;
329
330 Some(plane)
331 });
332
333 if planes.iter().any(|p| p.is_none()) {
334 return None;
335 }
336
337 Some(planes.map(|p| BytePlaneMut { inner: p.unwrap() }))
338 }
339
340 pub fn set_color(&mut self, color: Color) -> Result<(), LayoutError> {
345 self.inner.layout_mut_unguarded().set_color(color)
346 }
347
348 pub(crate) fn as_mut(&mut self) -> ImageMut<'_, &'_ mut CanvasLayout> {
349 self.inner.as_mut()
350 }
351}
352
353impl Canvas {
355 pub fn convert(&self, into: &mut Self) -> Result<(), crate::shader::ConversionError> {
365 Converter::new().run_to_completion(self, into)
366 }
367}
368
369impl RcCanvas {
370 pub fn new(layout: CanvasLayout) -> Self {
371 RcCanvas {
372 inner: CellImage::new(layout),
373 }
374 }
375
376 pub fn plane(&self, idx: u8) -> Option<BytePlaneCells<'_>> {
381 let [plane] = self.inner.as_ref().into_planes([PlaneIdx(idx)]).ok()?;
382 Some(BytePlaneCells { inner: plane })
383 }
384
385 pub fn to_canvas(&self) -> Canvas {
386 Canvas {
387 inner: self.inner.clone().into_owned(),
388 }
389 }
390}
391
392impl ArcCanvas {
393 pub fn new(layout: CanvasLayout) -> Self {
394 ArcCanvas {
395 inner: AtomicImage::new(layout),
396 }
397 }
398
399 pub fn plane(&self, idx: u8) -> Option<BytePlaneAtomics<'_>> {
404 let [plane] = self.inner.as_ref().into_planes([PlaneIdx(idx)]).ok()?;
405 Some(BytePlaneAtomics { inner: plane })
406 }
407
408 pub fn to_canvas(&self) -> Canvas {
409 Canvas {
410 inner: self.inner.clone().into_owned(),
411 }
412 }
413}
414
415impl<'data> BytePlaneRef<'data> {
416 pub fn layout(&self) -> &PlaneBytes {
417 self.inner.layout()
418 }
419
420 pub fn to_owned(&self) -> Plane {
421 let plane = self.inner.layout();
422 let bytes = self.inner.as_bytes();
423
424 Plane {
425 inner: Image::with_bytes(plane.clone(), bytes),
426 }
427 }
428
429 pub fn to_canvas(&self) -> Canvas {
430 let plane = self.inner.layout();
431 let bytes = self.inner.as_bytes();
432
433 Canvas {
434 inner: Image::with_bytes(plane.into(), bytes),
435 }
436 }
437
438 pub fn as_texels<T>(self, texel: image_texel::Texel<T>) -> Option<PlaneRef<'data, T>> {
440 if let Some(layout) = self.inner.layout().is_compatible(texel) {
441 Some(PlaneRef {
442 inner: self.inner.with_layout(layout).unwrap(),
443 })
444 } else {
445 None
446 }
447 }
448}
449
450impl<'data> BytePlaneMut<'data> {
451 pub fn layout(&self) -> &PlaneBytes {
452 self.inner.layout()
453 }
454
455 pub fn to_owned(&self) -> Plane {
456 let plane = self.inner.layout();
457 let bytes = self.inner.as_bytes();
458
459 Plane {
460 inner: Image::with_bytes(plane.clone(), bytes),
461 }
462 }
463
464 pub fn to_canvas(&self) -> Canvas {
465 let plane = self.inner.layout();
466 let bytes = self.inner.as_bytes();
467
468 Canvas {
469 inner: Image::with_bytes(plane.into(), bytes),
470 }
471 }
472
473 pub fn as_texels<T>(self, texel: image_texel::Texel<T>) -> Option<PlaneRef<'data, T>> {
475 if let Some(layout) = self.inner.layout().is_compatible(texel) {
476 Some(PlaneRef {
477 inner: self.inner.into_ref().with_layout(layout).unwrap(),
478 })
479 } else {
480 None
481 }
482 }
483
484 pub fn as_mut_texels<T>(self, texel: image_texel::Texel<T>) -> Option<PlaneMut<'data, T>> {
486 if let Some(layout) = self.inner.layout().is_compatible(texel) {
487 Some(PlaneMut {
488 inner: self.inner.with_layout(layout).unwrap(),
489 })
490 } else {
491 None
492 }
493 }
494}
495
496impl<'data> BytePlaneCells<'data> {
497 pub fn layout(&self) -> &PlaneBytes {
498 self.inner.layout()
499 }
500
501 pub fn to_owned(&self) -> Plane {
502 Plane {
503 inner: self.inner.clone().into_owned(),
504 }
505 }
506
507 pub fn to_canvas(&self) -> Canvas {
508 self.to_owned().into()
509 }
510}
511
512impl<'data> BytePlaneAtomics<'data> {
513 pub fn layout(&self) -> &PlaneBytes {
514 self.inner.layout()
515 }
516
517 pub fn to_owned(&self) -> Plane {
518 Plane {
519 inner: self.inner.clone().into_owned(),
520 }
521 }
522
523 pub fn to_canvas(&self) -> Canvas {
524 self.to_owned().into()
525 }
526}
527
528impl<'data, C> ChannelsRef<'data, C> {
529 pub fn layout(&self) -> &ChannelLayout<C> {
530 self.inner.layout()
531 }
532
533 pub fn as_slice(&self) -> &[C] {
534 self.inner.as_slice()
535 }
536
537 pub fn into_slice(self) -> &'data [C] {
538 self.inner.into_slice()
539 }
540}
541
542impl<'data, C> ChannelsMut<'data, C> {
543 pub fn layout(&self) -> &ChannelLayout<C> {
544 self.inner.layout()
545 }
546
547 pub fn as_slice(&self) -> &[C] {
548 self.inner.as_slice()
549 }
550
551 pub fn as_mut_slice(&mut self) -> &mut [C] {
552 self.inner.as_mut_slice()
553 }
554
555 pub fn into_slice(self) -> &'data [C] {
556 self.inner.into_slice()
557 }
558
559 pub fn into_mut_slice(self) -> &'data mut [C] {
560 self.inner.into_mut_slice()
561 }
562}
563
564impl<'data, T> From<PlaneRef<'data, T>> for BytePlaneRef<'data> {
565 fn from(plane: PlaneRef<'data, T>) -> Self {
566 BytePlaneRef {
567 inner: plane.inner.decay(),
568 }
569 }
570}
571
572impl<'data, T> From<PlaneMut<'data, T>> for BytePlaneMut<'data> {
573 fn from(plane: PlaneMut<'data, T>) -> Self {
574 BytePlaneMut {
575 inner: plane.inner.decay(),
576 }
577 }
578}
579
580impl From<Plane> for Canvas {
581 fn from(plane: Plane) -> Self {
582 Canvas {
583 inner: plane.inner.decay(),
584 }
585 }
586}
587
588impl From<Canvas> for RcCanvas {
589 fn from(canvas: Canvas) -> Self {
590 RcCanvas {
591 inner: CellImage::with_bytes(canvas.layout().clone(), canvas.as_bytes()),
592 }
593 }
594}
595
596impl From<Canvas> for ArcCanvas {
597 fn from(canvas: Canvas) -> Self {
598 ArcCanvas {
599 inner: AtomicImage::with_bytes(canvas.layout().clone(), canvas.as_bytes()),
600 }
601 }
602}
603
604impl From<RcCanvas> for Canvas {
605 fn from(canvas: RcCanvas) -> Self {
606 Canvas {
607 inner: canvas.inner.into_owned(),
608 }
609 }
610}
611
612impl From<ArcCanvas> for Canvas {
613 fn from(canvas: ArcCanvas) -> Self {
614 Canvas {
615 inner: canvas.inner.into_owned(),
616 }
617 }
618}
619
620impl From<RcCanvas> for ArcCanvas {
621 fn from(canvas: RcCanvas) -> Self {
622 let inner = canvas.inner;
626
627 let mut out = AtomicImage::new(inner.layout().clone());
628 let target = out.get_mut().expect("Still the sole owner");
629 U8.load_cell_slice(inner.as_texels(U8).as_slice_of_cells(), target.as_buf_mut());
630
631 ArcCanvas { inner: out }
632 }
633}
634
635impl From<ArcCanvas> for RcCanvas {
636 fn from(canvas: ArcCanvas) -> Self {
637 let inner = canvas.inner;
639
640 let out = CellImage::new(inner.layout().clone());
641 U8.load_atomic_to_cells(inner.as_texels(U8), out.as_texels(U8).as_slice_of_cells());
644
645 RcCanvas { inner: out }
646 }
647}