1//! Framebuffer.
2
3use core::{convert::Infallible, marker::PhantomData};
4
5use crate::{
6 draw_target::DrawTarget,
7 geometry::{OriginDimensions, Point, Size},
8 image::{GetPixel, ImageRaw},
9 iterator::raw::RawDataSlice,
10 pixelcolor::{
11 raw::{
12 BigEndian, ByteOrder, LittleEndian, RawData, RawU1, RawU16, RawU2, RawU24, RawU32,
13 RawU4, RawU8, ToBytes,
14 },
15 PixelColor,
16 },
17 Pixel,
18};
19
20/// Calculates the required buffer size.
21///
22/// This function is a workaround for current limitations in Rust const generics.
23/// It can be used to calculate the `N` parameter based on the size and color type of the framebuffer.
24pub const fn buffer_size<C: PixelColor>(width: usize, height: usize) -> usize {
25 buffer_size_bpp(width, height, C::Raw::BITS_PER_PIXEL)
26}
27
28/// Calculates the required buffer size.
29///
30/// This function is a workaround for current limitations in Rust const generics.
31/// It can be used to calculate the `N` parameter based on the size and bit depth of the framebuffer.
32pub const fn buffer_size_bpp(width: usize, height: usize, bpp: usize) -> usize {
33 (width * bpp + 7) / 8 * height
34}
35
36/// A framebuffer.
37///
38/// # Examples
39///
40/// ```
41/// use embedded_graphics::{
42/// framebuffer,
43/// framebuffer::{Framebuffer, buffer_size},
44/// pixelcolor::{Rgb565, raw::LittleEndian},
45/// prelude::*,
46/// primitives::PrimitiveStyle,
47/// };
48///
49/// let mut fb = Framebuffer::<Rgb565, _, LittleEndian, 320, 240, {buffer_size::<Rgb565>(320, 240)}>::new();
50///
51/// fb.bounding_box()
52/// .into_styled(PrimitiveStyle::with_stroke(Rgb565::RED, 1))
53/// .draw(&mut fb)
54/// .unwrap();
55/// ```
56#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
57pub struct Framebuffer<C, R, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> {
58 data: [u8; N],
59 color_type: PhantomData<C>,
60 raw_type: PhantomData<R>,
61 byte_order: PhantomData<BO>,
62 n_assert: (),
63}
64
65impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize>
66 Framebuffer<C, C::Raw, BO, WIDTH, HEIGHT, N>
67where
68 C: PixelColor,
69{
70 const BUFFER_SIZE: usize = buffer_size::<C>(WIDTH, HEIGHT);
71
72 /// Static assertion that N is correct.
73 // MSRV: remove N when constant generic expressions are stabilized
74 const CHECK_N: () = assert!(
75 N >= Self::BUFFER_SIZE,
76 "Invalid N: see Framebuffer documentation for more information"
77 );
78
79 /// Creates a new framebuffer.
80 pub const fn new() -> Self {
81 Self {
82 data: [0; N],
83 color_type: PhantomData,
84 raw_type: PhantomData,
85 byte_order: PhantomData,
86 n_assert: Self::CHECK_N,
87 }
88 }
89
90 /// Returns a reference to the raw framebuffer data.
91 pub const fn data(&self) -> &[u8; N] {
92 &self.data
93 }
94
95 /// Returns a mutable reference to the raw framebuffer data.
96 pub fn data_mut(&mut self) -> &mut [u8; N] {
97 &mut self.data
98 }
99}
100
101impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize>
102 Framebuffer<C, C::Raw, BO, WIDTH, HEIGHT, N>
103where
104 C: PixelColor + From<C::Raw>,
105 BO: ByteOrder,
106 for<'a> RawDataSlice<'a, C::Raw, BO>: IntoIterator<Item = C::Raw>,
107{
108 /// Returns an image based on the framebuffer content.
109 pub fn as_image(&self) -> ImageRaw<'_, C, BO> {
110 ImageRaw::new(&self.data[0..Self::BUFFER_SIZE], WIDTH as u32)
111 }
112}
113
114impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> GetPixel
115 for Framebuffer<C, C::Raw, BO, WIDTH, HEIGHT, N>
116where
117 C: PixelColor + From<C::Raw>,
118 BO: ByteOrder,
119 for<'a> RawDataSlice<'a, C::Raw, BO>: IntoIterator<Item = C::Raw>,
120{
121 type Color = C;
122
123 fn pixel(&self, p: Point) -> Option<C> {
124 self.as_image().pixel(p)
125 }
126}
127
128macro_rules! impl_bit {
129 ($raw_type:ident) => {
130 impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize>
131 Framebuffer<C, $raw_type, BO, WIDTH, HEIGHT, N>
132 where
133 C: PixelColor + Into<$raw_type>,
134 {
135 /// Sets the color of a pixel.
136 ///
137 /// Trying to set a pixel outside the framebuffer is a noop.
138 pub fn set_pixel(&mut self, p: Point, c: C) {
139 if let (Ok(x), Ok(y)) = (usize::try_from(p.x), usize::try_from(p.y)) {
140 if x < WIDTH && y < HEIGHT {
141 let pixels_per_bit = 8 / C::Raw::BITS_PER_PIXEL;
142 let bits_per_row = WIDTH * C::Raw::BITS_PER_PIXEL;
143 let bytes_per_row = (bits_per_row + 7) / 8;
144 let byte_index = bytes_per_row * y + (x / pixels_per_bit);
145 let bit_index = 8 - (x % pixels_per_bit + 1) * C::Raw::BITS_PER_PIXEL;
146
147 let mask = !((2u8.pow(C::Raw::BITS_PER_PIXEL as u32) - 1) << bit_index);
148 let bits = c.into().into_inner() << bit_index;
149
150 self.data[byte_index] = self.data[byte_index] & mask | bits;
151 }
152 }
153 }
154 }
155
156 impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> DrawTarget
157 for Framebuffer<C, $raw_type, BO, WIDTH, HEIGHT, N>
158 where
159 C: PixelColor<Raw = $raw_type> + Into<$raw_type>,
160 {
161 type Color = C;
162 type Error = Infallible;
163
164 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
165 where
166 I: IntoIterator<Item = Pixel<Self::Color>>,
167 {
168 for Pixel(p, c) in pixels {
169 self.set_pixel(p, c);
170 }
171
172 Ok(())
173 }
174 }
175 };
176}
177
178impl_bit!(RawU1);
179impl_bit!(RawU2);
180impl_bit!(RawU4);
181
182impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize>
183 Framebuffer<C, RawU8, BO, WIDTH, HEIGHT, N>
184where
185 C: PixelColor + Into<RawU8>,
186{
187 /// Sets the color of a pixel.
188 ///
189 /// Setting a pixel outside the framebuffer's bounding box will be a noop.
190 pub fn set_pixel(&mut self, p: Point, c: C) {
191 if let (Ok(x: usize), Ok(y: usize)) = (usize::try_from(p.x), usize::try_from(p.y)) {
192 if x < WIDTH && y < HEIGHT {
193 let x: usize = p.x as usize;
194 let y: usize = p.y as usize;
195
196 self.data[y * WIDTH + x] = c.into().into_inner();
197 }
198 }
199 }
200}
201
202impl<C, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> DrawTarget
203 for Framebuffer<C, RawU8, BO, WIDTH, HEIGHT, N>
204where
205 C: PixelColor<Raw = RawU8> + Into<RawU8>,
206{
207 type Color = C;
208 type Error = Infallible;
209
210 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
211 where
212 I: IntoIterator<Item = Pixel<Self::Color>>,
213 {
214 for Pixel(p: Point, c: C) in pixels {
215 self.set_pixel(p, c);
216 }
217
218 Ok(())
219 }
220}
221
222macro_rules! impl_bytes {
223 ($raw_type:ty, $bo_type:ty, $to_bytes_fn:ident) => {
224 impl<C, const WIDTH: usize, const HEIGHT: usize, const N: usize>
225 Framebuffer<C, $raw_type, $bo_type, WIDTH, HEIGHT, N>
226 where
227 C: PixelColor + Into<$raw_type>,
228 {
229 /// Sets the color of a pixel.
230 ///
231 /// Trying to set a pixel outside the framebuffer is a noop.
232 pub fn set_pixel(&mut self, p: Point, c: C) {
233 const BYTES_PER_PIXEL: usize = <$raw_type>::BITS_PER_PIXEL / 8;
234
235 if let (Ok(x), Ok(y)) = (usize::try_from(p.x), usize::try_from(p.y)) {
236 if x < WIDTH && y < HEIGHT {
237 let x = p.x as usize;
238 let y = p.y as usize;
239
240 let index = (y * WIDTH + x) * BYTES_PER_PIXEL;
241
242 self.data[index..index + BYTES_PER_PIXEL]
243 .copy_from_slice(&c.into().$to_bytes_fn());
244 }
245 }
246 }
247 }
248
249 impl<C, const WIDTH: usize, const HEIGHT: usize, const N: usize> DrawTarget
250 for Framebuffer<C, $raw_type, $bo_type, WIDTH, HEIGHT, N>
251 where
252 C: PixelColor<Raw = $raw_type> + Into<$raw_type>,
253 {
254 type Color = C;
255 type Error = Infallible;
256
257 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
258 where
259 I: IntoIterator<Item = Pixel<Self::Color>>,
260 {
261 for Pixel(p, c) in pixels {
262 self.set_pixel(p, c);
263 }
264
265 Ok(())
266 }
267 }
268 };
269
270 ($raw_type:ty) => {
271 impl_bytes!($raw_type, LittleEndian, to_le_bytes);
272 impl_bytes!($raw_type, BigEndian, to_be_bytes);
273 };
274}
275
276impl_bytes!(RawU16);
277impl_bytes!(RawU24);
278impl_bytes!(RawU32);
279
280impl<C, R, BO, const WIDTH: usize, const HEIGHT: usize, const N: usize> OriginDimensions
281 for Framebuffer<C, R, BO, WIDTH, HEIGHT, N>
282{
283 fn size(&self) -> Size {
284 Size::new(WIDTH as u32, HEIGHT as u32)
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use embedded_graphics_core::prelude::GrayColor;
291
292 use super::*;
293
294 use crate::{
295 geometry::Dimensions,
296 geometry::Point,
297 image::Image,
298 mock_display::MockDisplay,
299 pixelcolor::{BinaryColor, Gray2, Gray4, Gray8, Rgb565, Rgb888, RgbColor},
300 primitives::{Primitive, PrimitiveStyle},
301 Drawable,
302 };
303
304 /// Calculate the framebuffer generic constants.
305 macro_rules! framebuffer {
306 ($color_type:ty, $byte_order:ty, $width:expr, $height:expr) => {
307 $crate::framebuffer::Framebuffer::<
308 $color_type,
309 <$color_type as $crate::pixelcolor::PixelColor>::Raw,
310 $byte_order,
311 $width,
312 $height,
313 { $crate::framebuffer::buffer_size::<$color_type>($width, $height) },
314 >
315 };
316
317 ($color_type:ty, $width:expr, $height:expr) => {
318 $crate::framebuffer::Framebuffer::<
319 $color_type,
320 <$color_type as $crate::pixelcolor::PixelColor>::Raw,
321 $crate::pixelcolor::raw::LittleEndian,
322 $width,
323 $height,
324 { $crate::framebuffer::buffer_size::<$color_type>($width, $height) },
325 >
326 };
327 }
328
329 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
330 struct U32Color(u32);
331
332 impl PixelColor for U32Color {
333 type Raw = RawU32;
334 }
335
336 impl From<RawU32> for U32Color {
337 fn from(raw: RawU32) -> Self {
338 Self(raw.into_inner())
339 }
340 }
341
342 impl From<U32Color> for RawU32 {
343 fn from(color: U32Color) -> Self {
344 Self::new(color.0)
345 }
346 }
347
348 #[test]
349 fn raw_u1() {
350 let mut fb = <framebuffer!(BinaryColor, 9, 2)>::new();
351
352 use BinaryColor::{Off, On};
353 fb.draw_iter(
354 [
355 ((0, 0), On), //
356 ((8, 1), On), //
357 ((1, 1), On), //
358 ((1, 1), Off), //
359 ((-1, 0), On), //
360 ((0, -1), On), //
361 ((9, 0), On), //
362 ((0, 2), On), //
363 ]
364 .iter()
365 .map(|(p, c)| Pixel(Point::from(*p), *c)),
366 )
367 .unwrap();
368
369 assert_eq!(
370 fb.data(),
371 &[
372 0b10000000, 0b00000000, //
373 0b00000000, 0b10000000, //
374 ]
375 );
376 }
377
378 #[test]
379 fn raw_u2() {
380 type FB = framebuffer!(Gray2, 6, 4);
381 let mut fb = FB::new();
382
383 fb.draw_iter(
384 [
385 ((0, 0), 1), //
386 ((5, 3), 2), //
387 ((1, 1), 3), //
388 ((1, 2), 0), //
389 ((-1, 0), 3), //
390 ((0, -1), 3), //
391 ((6, 0), 3), //
392 ((0, 4), 3), //
393 ]
394 .iter()
395 .map(|(p, c)| Pixel(Point::from(*p), Gray2::new(*c))),
396 )
397 .unwrap();
398
399 assert_eq!(
400 fb.data(),
401 &[
402 0b01000000, 0b00000000, //
403 0b00110000, 0b00000000, //
404 0b00000000, 0b00000000, //
405 0b00000000, 0b00100000, //
406 ]
407 );
408 }
409
410 #[test]
411 fn raw_u4() {
412 let mut fb = <framebuffer!(Gray4, 3, 2)>::new();
413
414 fb.draw_iter(
415 [
416 ((0, 0), 0x1), //
417 ((2, 1), 0xF), //
418 ((1, 0), 0xA), //
419 ((1, 1), 0xB), //
420 ((-1, 0), 0xF), //
421 ((0, -1), 0xF), //
422 ((3, 0), 0xF), //
423 ((0, 2), 0xF), //
424 ]
425 .iter()
426 .map(|(p, c)| Pixel(Point::from(*p), Gray4::new(*c))),
427 )
428 .unwrap();
429
430 assert_eq!(
431 fb.data(),
432 &[
433 0x1A, 0x00, //
434 0x0B, 0xF0, //
435 ]
436 );
437 }
438
439 #[test]
440 fn raw_u8() {
441 let mut fb = <framebuffer!(Gray8, 3, 2)>::new();
442
443 fb.draw_iter(
444 [
445 ((0, 0), 0x10), //
446 ((2, 1), 0x22), //
447 ((1, 0), 0x3F), //
448 ((1, 1), 0xF0), //
449 ((-1, 0), 0xFF), //
450 ((0, -1), 0xFF), //
451 ((3, 0), 0xFF), //
452 ((0, 2), 0xFF), //
453 ]
454 .iter()
455 .map(|(p, c)| Pixel(Point::from(*p), Gray8::new(*c))),
456 )
457 .unwrap();
458
459 assert_eq!(
460 fb.data(),
461 &[
462 0x10, 0x3F, 0x00, //
463 0x00, 0xF0, 0x22, //
464 ]
465 );
466 }
467
468 #[test]
469 fn raw_u16_le() {
470 let mut fb = <framebuffer!(Rgb565, 3, 2)>::new();
471
472 fb.draw_iter(
473 [
474 ((0, 0), 0x1000), //
475 ((2, 1), 0x0001), //
476 ((1, 0), 0x1234), //
477 ((1, 1), 0x8765), //
478 ((-1, 0), 0xFFFF), //
479 ((0, -1), 0xFFFF), //
480 ((3, 0), 0xFFFF), //
481 ((0, 2), 0xFFFF), //
482 ]
483 .iter()
484 .map(|(p, c)| Pixel(Point::from(*p), Rgb565::from(RawU16::new(*c)))),
485 )
486 .unwrap();
487
488 assert_eq!(
489 fb.data(),
490 &[
491 0x00, 0x10, 0x34, 0x12, 0x00, 0x00, //
492 0x00, 0x00, 0x65, 0x87, 0x01, 0x00, //
493 ]
494 );
495 }
496
497 #[test]
498 fn raw_u16_be() {
499 let mut fb = <framebuffer!(Rgb565, BigEndian, 3, 2)>::new();
500
501 fb.draw_iter(
502 [
503 ((0, 0), 0x1000), //
504 ((2, 1), 0x0001), //
505 ((1, 0), 0x1234), //
506 ((1, 1), 0x8765), //
507 ((-1, 0), 0xFFFF), //
508 ((0, -1), 0xFFFF), //
509 ((3, 0), 0xFFFF), //
510 ((0, 2), 0xFFFF), //
511 ]
512 .iter()
513 .map(|(p, c)| Pixel(Point::from(*p), Rgb565::from(RawU16::new(*c)))),
514 )
515 .unwrap();
516
517 assert_eq!(
518 fb.data(),
519 &[
520 0x10, 0x00, 0x12, 0x34, 0x00, 0x00, //
521 0x00, 0x00, 0x87, 0x65, 0x00, 0x01, //
522 ]
523 );
524 }
525
526 #[test]
527 fn raw_u24_le() {
528 let mut fb = <framebuffer!(Rgb888, 3, 2)>::new();
529
530 fb.draw_iter(
531 [
532 ((0, 0), 0x100000), //
533 ((2, 1), 0x000001), //
534 ((1, 0), 0x123456), //
535 ((1, 1), 0x876543), //
536 ((-1, 0), 0xFFFFFF), //
537 ((0, -1), 0xFFFFFF), //
538 ((3, 0), 0xFFFFFF), //
539 ((0, 2), 0xFFFFFF), //
540 ]
541 .iter()
542 .map(|(p, c)| Pixel(Point::from(*p), Rgb888::from(RawU24::new(*c)))),
543 )
544 .unwrap();
545
546 assert_eq!(
547 fb.data(),
548 &[
549 0x00, 0x00, 0x10, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, //
550 0x00, 0x00, 0x00, 0x43, 0x65, 0x87, 0x01, 0x00, 0x00, //
551 ]
552 );
553 }
554
555 #[test]
556 fn raw_u24_be() {
557 let mut fb = <framebuffer!(Rgb888, BigEndian, 3, 2)>::new();
558
559 fb.draw_iter(
560 [
561 ((0, 0), 0x100000), //
562 ((2, 1), 0x000001), //
563 ((1, 0), 0x123456), //
564 ((1, 1), 0x876543), //
565 ((-1, 0), 0xFFFFFF), //
566 ((0, -1), 0xFFFFFF), //
567 ((3, 0), 0xFFFFFF), //
568 ((0, 2), 0xFFFFFF), //
569 ]
570 .iter()
571 .map(|(p, c)| Pixel(Point::from(*p), Rgb888::from(RawU24::new(*c)))),
572 )
573 .unwrap();
574
575 assert_eq!(
576 fb.data(),
577 &[
578 0x10, 0x00, 0x00, 0x12, 0x34, 0x56, 0x00, 0x00, 0x00, //
579 0x00, 0x00, 0x00, 0x87, 0x65, 0x43, 0x00, 0x00, 0x01, //
580 ]
581 );
582 }
583
584 #[test]
585 fn raw_u32_le() {
586 let mut fb = <framebuffer!(U32Color, 3, 2)>::new();
587
588 fb.draw_iter(
589 [
590 ((0, 0), 0x10000000), //
591 ((2, 1), 0x00000001), //
592 ((1, 0), 0x12345678), //
593 ((1, 1), 0x87654321), //
594 ((-1, 0), 0xFFFFFFFF), //
595 ((0, -1), 0xFFFFFFFF), //
596 ((3, 0), 0xFFFFFFFF), //
597 ((0, 2), 0xFFFFFFFF), //
598 ]
599 .iter()
600 .map(|(p, c)| Pixel(Point::from(*p), U32Color::from(RawU32::new(*c)))),
601 )
602 .unwrap();
603
604 assert_eq!(
605 fb.data(),
606 &[
607 0x00, 0x00, 0x00, 0x10, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, //
608 0x00, 0x00, 0x00, 0x00, 0x21, 0x43, 0x65, 0x87, 0x01, 0x00, 0x00, 0x00, //
609 ]
610 );
611 }
612
613 #[test]
614 fn raw_u32_be() {
615 let mut fb = <framebuffer!(U32Color, BigEndian, 3, 2)>::new();
616
617 fb.draw_iter(
618 [
619 ((0, 0), 0x10000000), //
620 ((2, 1), 0x00000001), //
621 ((1, 0), 0x12345678), //
622 ((1, 1), 0x87654321), //
623 ((-1, 0), 0xFFFFFFFF), //
624 ((0, -1), 0xFFFFFFFF), //
625 ((3, 0), 0xFFFFFFFF), //
626 ((0, 2), 0xFFFFFFFF), //
627 ]
628 .iter()
629 .map(|(p, c)| Pixel(Point::from(*p), U32Color::from(RawU32::new(*c)))),
630 )
631 .unwrap();
632
633 assert_eq!(
634 fb.data(),
635 &[
636 0x10, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, //
637 0x00, 0x00, 0x00, 0x00, 0x87, 0x65, 0x43, 0x21, 0x00, 0x00, 0x00, 0x01, //
638 ]
639 );
640 }
641
642 #[test]
643 fn as_image() {
644 let mut fb = <framebuffer!(BinaryColor, 10, 10)>::new();
645
646 fb.bounding_box()
647 .into_styled(PrimitiveStyle::with_stroke(BinaryColor::On, 1))
648 .draw(&mut fb)
649 .unwrap();
650
651 fb.draw_iter(
652 [(7, 2), (8, 8)]
653 .into_iter()
654 .map(|p| Pixel(Point::from(p), BinaryColor::On)),
655 )
656 .unwrap();
657
658 let mut display = MockDisplay::<BinaryColor>::new();
659 Image::new(&fb.as_image(), Point::new(2, 1))
660 .draw(&mut display)
661 .unwrap();
662
663 display.assert_pattern(&[
664 " ",
665 " ##########",
666 " #........#",
667 " #......#.#",
668 " #........#",
669 " #........#",
670 " #........#",
671 " #........#",
672 " #........#",
673 " #.......##",
674 " ##########",
675 ]);
676 }
677
678 #[test]
679 fn pixel() {
680 let mut fb = <framebuffer!(BinaryColor, 10, 10)>::new();
681
682 fb.draw_iter(
683 [(7, 2), (8, 8)]
684 .into_iter()
685 .map(|p| Pixel(Point::from(p), BinaryColor::On)),
686 )
687 .unwrap();
688
689 let expected = [
690 ((0, 0), Some(BinaryColor::Off)),
691 ((1, 0), Some(BinaryColor::Off)),
692 ((1, 1), Some(BinaryColor::Off)),
693 ((7, 2), Some(BinaryColor::On)),
694 ((8, 8), Some(BinaryColor::On)),
695 ((-1, 0), None),
696 ((0, -1), None),
697 ((10, 0), None),
698 ((0, 10), None),
699 ];
700 for (p, c) in expected {
701 assert_eq!(fb.pixel(p.into()), c, "{p:?}");
702 }
703 }
704
705 #[test]
706 fn set_pixel() {
707 // This tests only checks that the set_pixel methods are present for all BPPs.
708 // The correct function is tested indirectly in the DrawTarget tests.
709
710 <framebuffer!(BinaryColor, 10, 10)>::new().set_pixel(Point::zero(), BinaryColor::On);
711 <framebuffer!(Gray2, 10, 10)>::new().set_pixel(Point::zero(), Gray2::WHITE);
712 <framebuffer!(Gray4, 10, 10)>::new().set_pixel(Point::zero(), Gray4::WHITE);
713 <framebuffer!(Gray8, 10, 10)>::new().set_pixel(Point::zero(), Gray8::WHITE);
714 <framebuffer!(Rgb565, 10, 10)>::new().set_pixel(Point::zero(), Rgb565::WHITE);
715 <framebuffer!(Rgb888, 10, 10)>::new().set_pixel(Point::zero(), Rgb888::WHITE);
716 <framebuffer!(U32Color, 10, 10)>::new().set_pixel(Point::zero(), U32Color(0));
717 }
718
719 #[test]
720 fn oversized_buffer() {
721 let fb = Framebuffer::<
722 BinaryColor,
723 _,
724 LittleEndian,
725 10,
726 5,
727 { buffer_size::<BinaryColor>(10, 5) * 3 / 2 },
728 >::new();
729
730 assert_eq!(fb.size(), Size::new(10, 5));
731 assert_eq!(fb.as_image().size(), Size::new(10, 5));
732
733 let outside_x = Point::zero() + fb.size().x_axis();
734 let outside_y = Point::zero() + fb.size().y_axis();
735
736 assert_eq!(fb.pixel(outside_x), None);
737 assert_eq!(fb.pixel(outside_y), None);
738
739 let mut fb2 = fb.clone();
740 fb2.set_pixel(outside_x, BinaryColor::On);
741 fb2.set_pixel(outside_y, BinaryColor::On);
742
743 assert_eq!(fb, fb2);
744 }
745}
746