freenukum/
rendering.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
3
4use crate::Result;
5use crate::TileProvider;
6use anyhow::Error;
7use sdl2::{
8    pixels::Color,
9    rect::{Point, Rect},
10    render::{Canvas, RenderTarget, TextureCreator},
11    surface::Surface,
12};
13
14pub type TileIndex = usize;
15
16pub trait Renderer {
17    fn place_surface(
18        &mut self,
19        surface: &Surface,
20        rect: Rect,
21    ) -> Result<()>;
22
23    fn place_tile(
24        &mut self,
25        tile: TileIndex,
26        destination: Point,
27    ) -> Result<()>;
28    fn fill_rect(&mut self, rect: Rect, color: Color) -> Result<()>;
29    fn fill(&mut self, color: Color) -> Result<()>;
30    fn draw_rect(&mut self, rect: Rect, color: Color) -> Result<()>;
31}
32
33pub struct MovePositionRenderer<'a> {
34    pub offset_x: i32,
35    pub offset_y: i32,
36    pub upstream: &'a mut dyn Renderer,
37}
38
39impl<'a> Renderer for MovePositionRenderer<'a> {
40    fn place_surface(
41        &mut self,
42        surface: &Surface,
43        mut rect: Rect,
44    ) -> Result<()> {
45        rect.offset(self.offset_x, self.offset_y);
46        self.upstream.place_surface(surface, rect)
47    }
48
49    fn place_tile(
50        &mut self,
51        tile: TileIndex,
52        destination: Point,
53    ) -> Result<()> {
54        self.upstream.place_tile(
55            tile,
56            destination.offset(self.offset_x, self.offset_y),
57        )
58    }
59
60    fn fill_rect(&mut self, mut rect: Rect, color: Color) -> Result<()> {
61        rect.offset(self.offset_x, self.offset_y);
62        self.upstream.fill_rect(rect, color)
63    }
64
65    fn fill(&mut self, color: Color) -> Result<()> {
66        self.upstream.fill(color)
67    }
68
69    fn draw_rect(&mut self, mut rect: Rect, color: Color) -> Result<()> {
70        rect.offset(self.offset_x, self.offset_y);
71        self.upstream.draw_rect(rect, color)
72    }
73}
74
75pub struct CanvasRenderer<'a, RT: RenderTarget, T> {
76    pub canvas: &'a mut Canvas<RT>,
77    pub texture_creator: &'a TextureCreator<T>,
78    pub tileprovider: &'a dyn TileProvider,
79}
80
81impl<'a, RT: RenderTarget, T> Renderer for CanvasRenderer<'a, RT, T> {
82    fn place_surface(
83        &mut self,
84        surface: &Surface,
85        rect: Rect,
86    ) -> Result<()> {
87        self.canvas
88            .copy(&surface.as_texture(self.texture_creator)?, None, rect)
89            .map_err(Error::msg)?;
90        Ok(())
91    }
92
93    fn place_tile(
94        &mut self,
95        tile: TileIndex,
96        destination: Point,
97    ) -> Result<()> {
98        let tile = self.tileprovider.get_tile(tile).unwrap();
99        let rect = Rect::new(
100            destination.x,
101            destination.y,
102            tile.width(),
103            tile.height(),
104        );
105        self.canvas
106            .copy(&tile.as_texture(self.texture_creator)?, None, rect)
107            .map_err(Error::msg)?;
108        Ok(())
109    }
110
111    fn fill_rect(&mut self, rect: Rect, color: Color) -> Result<()> {
112        self.canvas.set_draw_color(color);
113        self.canvas.fill_rect(rect).map_err(Error::msg)?;
114        Ok(())
115    }
116
117    fn fill(&mut self, color: Color) -> Result<()> {
118        self.canvas.set_draw_color(color);
119        self.canvas.clear();
120        Ok(())
121    }
122
123    fn draw_rect(&mut self, rect: Rect, color: Color) -> Result<()> {
124        self.canvas.set_draw_color(color);
125        self.canvas.draw_rect(rect).map_err(Error::msg)?;
126        Ok(())
127    }
128}