rich_sdl2_rust/video/
surface.rs

1//! Surface, providing flexible modification for the pixels.
2
3use std::ptr::NonNull;
4
5use crate::color::pixel::Pixel;
6use crate::color::{BlendMode, Rgb};
7use crate::geo::{Point, Rect};
8use crate::{as_raw, color::pixel::palette::Palette};
9use crate::{bind, Sdl};
10pub use bind::SDL_Surface as RawSurface;
11
12pub mod alpha;
13pub mod blend;
14pub mod bmp;
15pub mod clipped;
16pub mod cloned;
17pub mod color;
18pub mod owned;
19pub mod rle;
20pub mod window;
21
22use alpha::AlphaMod;
23use blend::Blended;
24use clipped::Clipped;
25use cloned::Cloned;
26use color::ColorMod;
27use rle::Rle;
28
29/// A trait that provides flexible modification methods.
30pub trait Surface {
31    /// Returns the raw non-null pointer.
32    fn as_ptr(&self) -> NonNull<RawSurface>;
33
34    /// Clones the surface.
35    fn cloned(&self) -> Cloned {
36        Cloned::new(self.as_ptr())
37    }
38
39    /// Clips the surface by `area`.
40    fn clipped(self, area: Rect) -> Clipped<Self>
41    where
42        Self: Sized,
43    {
44        Clipped::new(self, area)
45    }
46
47    /// Changes blend mode of the surface.
48    fn blend(self, mode: BlendMode) -> Blended<Self>
49    where
50        Self: Sized,
51    {
52        Blended::new(self, mode)
53    }
54
55    /// Modifies the alpha of the surface.
56    fn alpha_mod(self, alpha: u8) -> AlphaMod<Self>
57    where
58        Self: Sized,
59    {
60        AlphaMod::new(self, alpha)
61    }
62
63    /// Modifies the color of the surface.
64    fn color_mod(self, color: Rgb) -> ColorMod<Self>
65    where
66        Self: Sized,
67    {
68        ColorMod::new(self, color)
69    }
70
71    /// Fills in the `area` with the `color`, or whole if `area` is `None`.
72    fn fill_rect(&self, area: Option<Rect>, color: Pixel) {
73        let area = area.map(Into::into);
74        unsafe {
75            let ret = bind::SDL_FillRect(self.as_ptr().as_ptr(), as_raw(&area), color.as_u32());
76            if ret != 0 {
77                Sdl::error_then_panic("Surface filling with rectangle")
78            }
79        }
80    }
81
82    /// Fills in the `areas` with the `color`.
83    fn fill_rects(&self, areas: impl IntoIterator<Item = Rect>, color: Pixel) {
84        let raw_rects: Vec<_> = areas.into_iter().map(Into::into).collect();
85        unsafe {
86            let ret = bind::SDL_FillRects(
87                self.as_ptr().as_ptr(),
88                raw_rects.as_ptr(),
89                raw_rects.len() as i32,
90                color.as_u32(),
91            );
92            if ret != 0 {
93                Sdl::error_then_panic("Surface filling with rectangles")
94            }
95        }
96    }
97
98    /// Overwrites the palette of the surface.
99    fn set_palette(&self, palette: &Palette) {
100        let ret = unsafe { bind::SDL_SetSurfacePalette(self.as_ptr().as_ptr(), palette.as_ptr()) };
101        if ret != 0 {
102            Sdl::error_then_panic("Surface setting palette");
103        }
104    }
105
106    /// Copies `src_area` area in the surface into `dst_pos` on another surface.
107    fn copy_to<S: Surface>(&self, src_area: Rect, dst: &S, dst_pos: Point) {
108        let src_rect = src_area.into();
109        let mut dst_rect = bind::SDL_Rect {
110            x: dst_pos.x,
111            y: dst_pos.y,
112            w: 0,
113            h: 0,
114        };
115        let ret = unsafe {
116            bind::SDL_UpperBlit(
117                self.as_ptr().as_ptr(),
118                &src_rect,
119                dst.as_ptr().as_ptr(),
120                &mut dst_rect,
121            )
122        };
123        if ret != 0 {
124            Sdl::error_then_panic("Surface copying to another");
125        }
126    }
127
128    /// Run-length encodes the surface.
129    fn rle(&'_ mut self) -> Rle<'_, Self>
130    where
131        Self: Sized,
132    {
133        Rle::new(self)
134    }
135}