rich_sdl2_rust/video/renderer/
paste.rs

1#![allow(clippy::unnecessary_cast)]
2
3use bitflags::bitflags;
4
5use crate::texture::Texture;
6use crate::{
7    as_raw,
8    geo::{Point, Rect},
9};
10use crate::{bind, EnumInt, Sdl};
11
12use super::Renderer;
13
14bitflags! {
15    /// Flip mode on pasting from another texture.
16    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17    pub struct PasteExFlip: u32 {
18        /// Flips horizontal.
19        const HORIZONTAL = bind::SDL_FLIP_HORIZONTAL as u32;
20        /// Flips vertical.
21        const VERTICAL = bind::SDL_FLIP_VERTICAL as u32;
22        /// Flips both horizontal and vertical.
23        const BOTH = Self::HORIZONTAL.bits() | Self::VERTICAL.bits();
24    }
25}
26
27impl Default for PasteExFlip {
28    fn default() -> Self {
29        Self::empty()
30    }
31}
32
33/// An option for [`PasteExt::paste_ex`].
34#[derive(Debug, Default, Clone, Copy, PartialEq)]
35pub struct PasteExOption {
36    /// The target area of pasting, or whole if `None`.
37    pub target_area: Option<Rect>,
38    /// The degrees of rotating another texture.
39    pub rotation_degrees: f64,
40    /// The center point of pasting.
41    pub center: Option<Point>,
42    /// The flip mode of pasting.
43    pub flip: PasteExFlip,
44}
45
46/// A paster controls pasting from a texture.
47///
48/// This will render when be dropped. So you should re-create on every render.
49#[derive(Debug)]
50pub struct Paster<'renderer> {
51    renderer: &'renderer Renderer<'renderer>,
52}
53
54impl<'renderer> Drop for Paster<'renderer> {
55    fn drop(&mut self) {
56        unsafe { bind::SDL_RenderPresent(self.renderer.as_ptr()) }
57    }
58}
59
60impl<'renderer> Paster<'renderer> {
61    /// Constructs a pen from the renderer [`Renderer`].
62    #[must_use]
63    pub fn new(renderer: &'renderer Renderer) -> Self {
64        Self { renderer }
65    }
66
67    /// Returns the renderer that the pen is drawing.
68    #[must_use]
69    pub fn renderer(&self) -> &Renderer {
70        self.renderer
71    }
72}
73
74impl Paster<'_> {
75    /// Pastes the texture into `target_area`, or whole if `None`.
76    pub fn paste(&self, texture: &Texture, target_area: Option<Rect>) {
77        let src = texture.clip().map(Into::into);
78        let dst = target_area.map(Into::into);
79        let ret = unsafe {
80            bind::SDL_RenderCopy(
81                self.renderer.as_ptr(),
82                texture.as_ptr(),
83                as_raw(&src),
84                as_raw(&dst),
85            )
86        };
87        if ret != 0 {
88            Sdl::error_then_panic("Pasting texture to renderer");
89        }
90    }
91
92    /// Pastes the texture with options [`PasteExOption`].
93    pub fn paste_ex(
94        &self,
95        texture: &Texture,
96        PasteExOption {
97            target_area,
98            rotation_degrees,
99            center,
100            flip,
101        }: PasteExOption,
102    ) {
103        let src = texture.clip().map(Into::into);
104        let dst = target_area.map(Into::into);
105        let center = center.map(Into::into);
106        let ret = unsafe {
107            bind::SDL_RenderCopyEx(
108                self.renderer.as_ptr(),
109                texture.as_ptr(),
110                as_raw(&src),
111                as_raw(&dst),
112                rotation_degrees,
113                as_raw(&center),
114                flip.bits() as EnumInt,
115            )
116        };
117        if ret != 0 {
118            Sdl::error_then_panic("Pasting texture to renderer ex");
119        }
120    }
121}