graphics/
image.rs

1//! Draw an image
2
3use crate::{
4    math::Matrix2d,
5    triangulation,
6    types::{Color, Rectangle, SourceRectangle},
7    DrawState, Graphics, ImageSize,
8};
9
10/// An image
11///
12/// # Example
13///
14/// ```ignore
15/// extern crate piston;
16/// extern crate graphics;
17/// extern crate glutin_window;
18/// extern crate opengl_graphics;
19///
20/// use piston::window::WindowSettings;
21/// use piston::event::*;
22/// use glutin_window::GlutinWindow as Window;
23/// use opengl_graphics::{GlGraphics, OpenGL, Texture};
24/// use graphics::{Image, clear, default_draw_state};
25/// use graphics::rectangle::square;
26/// use std::path::Path;
27///
28/// fn main() {
29///     let opengl  = OpenGL::_3_2;
30///     let mut gl  = GlGraphics::new(opengl);
31///     let window  = Window::new(
32///             opengl,
33///             WindowSettings::new(
34///                 "Example",
35///                 [600, 400]
36///             ).exit_on_esc(true));
37///
38///     // Create the image object and attach a square Rectangle object inside.
39///     let image   = Image::new().rect(square(0.0, 0.0, 200.0));
40///     // A texture to use with the image
41///     let texture = Texture::from_path(Path::new("Example.png")).unwrap();
42///
43///     // Main loop
44///     for e in window.events() {
45///         if let Some(r) = e.render_args() {
46///             gl.draw(r.viewport(), |c, gl| {
47///                 //Clear the screen
48///                 clear([0.0, 0.0, 0.0, 1.0], gl);
49///                 //Draw the image with the texture
50///                 image.draw(&texture, default_draw_state(), c.transform, gl);
51///             });
52///         }
53///     }
54/// }
55/// ```
56#[derive(Copy, Clone)]
57pub struct Image {
58    /// The color
59    pub color: Option<Color>,
60    /// The rectangle to draw image inside
61    pub rectangle: Option<Rectangle>,
62    /// The image source rectangle
63    pub source_rectangle: Option<SourceRectangle>,
64}
65
66impl Image {
67    /// Creates a new image
68    pub fn new() -> Image {
69        Image {
70            color: None,
71            source_rectangle: None,
72            rectangle: None,
73        }
74    }
75
76    /// Creates a new colored image
77    pub fn new_color(color: Color) -> Image {
78        Image {
79            color: Some(color),
80            source_rectangle: None,
81            rectangle: None,
82        }
83    }
84
85    /// Sets color.
86    pub fn color(mut self, value: Color) -> Self {
87        self.color = Some(value);
88        self
89    }
90
91    /// Sets optional color.
92    pub fn maybe_color(mut self, value: Option<Color>) -> Self {
93        self.color = value;
94        self
95    }
96
97    /// Sets rectangle.
98    pub fn rect<R: Into<Rectangle>>(mut self, value: R) -> Self {
99        self.rectangle = Some(value.into());
100        self
101    }
102
103    /// Sets optional rectangle.
104    pub fn maybe_rect<R: Into<Rectangle>>(mut self, value: Option<R>) -> Self {
105        self.rectangle = value.map(|v| v.into());
106        self
107    }
108
109    /// Sets source rectangle.
110    pub fn src_rect(mut self, value: SourceRectangle) -> Self {
111        self.source_rectangle = Some(value);
112        self
113    }
114
115    /// Sets optional source rectangle.
116    pub fn maybe_src_rect(mut self, value: Option<SourceRectangle>) -> Self {
117        self.source_rectangle = value;
118        self
119    }
120
121    /// Draws image using default method.
122    #[inline(always)]
123    pub fn draw<G>(
124        &self,
125        texture: &<G as Graphics>::Texture,
126        draw_state: &DrawState,
127        transform: Matrix2d,
128        g: &mut G,
129    ) where
130        G: Graphics,
131    {
132        g.image(self, texture, draw_state, transform);
133    }
134
135    /// Draws image using triangulation.
136    pub fn draw_tri<G>(
137        &self,
138        texture: &<G as Graphics>::Texture,
139        draw_state: &DrawState,
140        transform: Matrix2d,
141        g: &mut G,
142    ) where
143        G: Graphics,
144    {
145        use crate::math::Scalar;
146
147        let color = self.color.unwrap_or([1.0; 4]);
148        let source_rectangle = self.source_rectangle.unwrap_or({
149            let (w, h) = texture.get_size();
150            [0.0, 0.0, w as Scalar, h as Scalar]
151        });
152        let rectangle = self.rectangle.unwrap_or([
153            0.0,
154            0.0,
155            source_rectangle[2] as Scalar,
156            source_rectangle[3] as Scalar,
157        ]);
158        g.tri_list_uv(draw_state, &color, texture, |f| {
159            f(
160                &triangulation::rect_tri_list_xy(transform, rectangle),
161                &triangulation::rect_tri_list_uv(texture, source_rectangle),
162            )
163        });
164    }
165}
166
167impl  Default for Image {
168    fn default() -> Self {
169        Image::new()
170    }
171}
172
173/// Draws many images.
174pub fn draw_many<G>(
175    rects: &[(Rectangle, SourceRectangle)],
176    color: Color,
177    texture: &<G as Graphics>::Texture,
178    draw_state: &DrawState,
179    transform: Matrix2d,
180    g: &mut G,
181) where
182    G: Graphics,
183{
184    g.tri_list_uv(draw_state, &color, texture, |f| {
185        for r in rects {
186            f(
187                &triangulation::rect_tri_list_xy(transform, r.0),
188                &triangulation::rect_tri_list_uv(texture, r.1),
189            )
190        }
191    });
192}
193
194#[cfg(test)]
195mod test {
196    use super::Image;
197
198    #[test]
199    fn test_image() {
200        let _img = Image::new()
201            .color([1.0; 4])
202            .rect([0.0, 0.0, 100.0, 100.0])
203            .src_rect([0.0, 0.0, 32.0, 32.0]);
204    }
205}