fltk/
surface.rs

1use crate::prelude::*;
2use crate::utils::FlString;
3use fltk_sys::surface::*;
4use std::ffi::CString;
5use std::path;
6
7/**
8    An image surface object.
9    Example usage:
10    ```rust,no_run
11    use fltk::{prelude::*, *};
12    let but = button::Button::new(0, 0, 80, 40, "Click");
13    let sur = surface::ImageSurface::new(but.w(), but.h(), false);
14    surface::ImageSurface::push_current(&sur);
15    draw::set_draw_color(enums::Color::White);
16    draw::draw_rectf(0, 0, but.w(), but.h());
17    sur.draw(&but, 0, 0);
18    let img = sur.image().unwrap();
19    surface::ImageSurface::pop_current();
20    ```
21*/
22pub struct ImageSurface {
23    inner: *mut Fl_Image_Surface,
24}
25
26impl SurfaceDevice for ImageSurface {
27    fn is_current(&self) -> bool {
28        unsafe { Fl_Surface_Device_is_current(self.inner as *mut _) != 0 }
29    }
30
31    fn surface() -> Self {
32        unsafe {
33            let ptr = Fl_Surface_Device_surface();
34            assert!(!ptr.is_null());
35            Self {
36                inner: ptr as *mut _,
37            }
38        }
39    }
40
41    fn push_current(new_current: &ImageSurface) {
42        unsafe { Fl_Surface_Device_push_current(new_current.inner as *mut _) }
43    }
44
45    fn pop_current() {
46        unsafe {
47            Fl_Surface_Device_pop_current();
48        }
49    }
50}
51
52impl ImageSurface {
53    /// Creates a new image surface
54    pub fn new(w: i32, h: i32, high_res: bool) -> ImageSurface {
55        unsafe {
56            let ptr = Fl_Image_Surface_new(w, h, i32::from(high_res));
57            assert!(!ptr.is_null());
58            ImageSurface { inner: ptr }
59        }
60    }
61
62    /// Gets the image of an image surface as an rgb image
63    pub fn image(&self) -> Option<crate::image::RgbImage> {
64        unsafe {
65            let ptr = Fl_Image_Surface_image(self.inner);
66            if ptr.is_null() {
67                None
68            } else {
69                Some(crate::image::RgbImage::from_image_ptr(ptr as *mut _))
70            }
71        }
72    }
73
74    #[cfg(feature = "use-images")]
75    /// Gets the high resolution image of an image surface as a shared image
76    pub fn highres_image(&self) -> Option<crate::image::SharedImage> {
77        unsafe {
78            let ptr = Fl_Image_Surface_highres_image(self.inner);
79            if ptr.is_null() {
80                None
81            } else {
82                Some(crate::image::SharedImage::from_image_ptr(ptr as *mut _))
83            }
84        }
85    }
86
87    /// Gets the origin coordinates of an image surface
88    pub fn origin(&self) -> (i32, i32) {
89        unsafe {
90            let mut x = 0;
91            let mut y = 0;
92            Fl_Image_Surface_origin(self.inner, &mut x, &mut y);
93            (x, y)
94        }
95    }
96
97    /// Set the origin coordinates of an image surface
98    pub fn set_origin(&mut self, x: i32, y: i32) {
99        unsafe { Fl_Image_Surface_set_origin(self.inner, x, y) }
100    }
101
102    /// Rescale an image surface
103    pub fn rescale(&mut self) {
104        unsafe { Fl_Image_Surface_rescale(self.inner) }
105    }
106
107    /// Draw a widget on the image surface
108    pub fn draw<W: WidgetExt>(&self, widget: &W, delta_x: i32, delta_y: i32) {
109        unsafe {
110            Fl_Image_Surface_draw(
111                self.inner,
112                widget.as_widget_ptr() as *mut _,
113                delta_x,
114                delta_y,
115            );
116        }
117    }
118
119    /// draw a decorated window
120    pub fn draw_decorated_window<W: WindowExt>(&self, win: &W, x_offset: i32, y_offset: i32) {
121        unsafe {
122            Fl_Image_Surface_draw_decorated_window(
123                self.inner,
124                win.as_widget_ptr() as *mut _,
125                x_offset,
126                y_offset,
127            );
128        }
129    }
130}
131
132impl Drop for ImageSurface {
133    fn drop(&mut self) {
134        unsafe { Fl_Image_Surface_delete(self.inner) }
135    }
136}
137
138/**
139    An SVG image surface object which allows drawing to an svg file
140    Example usage:
141    ```rust,no_run
142    use fltk::{prelude::*, *};
143    let but = button::Button::new(0, 0, 80, 40, "Click");
144    // We need the destructor of SvgFileSurface to actually create the image
145    {
146        let sur = surface::SvgFileSurface::new(but.w(), but.h(), "temp.svg");
147        surface::SvgFileSurface::push_current(&sur);
148        draw::set_draw_color(enums::Color::White);
149        draw::draw_rectf(0, 0, but.w(), but.h());
150        sur.draw(&but, 0, 0);
151        surface::SvgFileSurface::pop_current();
152    }
153    ```
154*/
155pub struct SvgFileSurface {
156    inner: *mut Fl_SVG_File_Surface,
157}
158
159impl SurfaceDevice for SvgFileSurface {
160    fn is_current(&self) -> bool {
161        unsafe { Fl_Surface_Device_is_current(self.inner as *mut _) != 0 }
162    }
163
164    fn surface() -> Self {
165        unsafe {
166            let ptr = Fl_Surface_Device_surface();
167            assert!(!ptr.is_null());
168            Self {
169                inner: ptr as *mut _,
170            }
171        }
172    }
173
174    fn push_current(new_current: &SvgFileSurface) {
175        unsafe { Fl_Surface_Device_push_current(new_current.inner as *mut _) }
176    }
177
178    fn pop_current() {
179        unsafe {
180            Fl_Surface_Device_pop_current();
181        }
182    }
183}
184
185impl SvgFileSurface {
186    /// Returns a new `SvgFileSurface`. The path if non-existent will be created
187    /// # Panics
188    /// Panics on File creation failure and on writablity failure
189    pub fn new<P: AsRef<path::Path>>(width: i32, height: i32, path: P) -> SvgFileSurface {
190        if path.as_ref().exists() {
191            let f = std::fs::File::open(path.as_ref()).unwrap();
192            assert!(!f.metadata().unwrap().permissions().readonly());
193        } else {
194            let f = std::fs::File::create(path.as_ref()).unwrap();
195            assert!(!f.metadata().unwrap().permissions().readonly());
196        }
197        let path = CString::safe_new(path.as_ref().to_str().unwrap());
198        unsafe {
199            let ptr = Fl_SVG_File_Surface_new(width, height, path.as_ptr());
200            assert!(!ptr.is_null());
201            SvgFileSurface { inner: ptr }
202        }
203    }
204
205    /// Sets the origin of the `SvgFileSurface`
206    pub fn set_origin(&mut self, x: i32, y: i32) {
207        unsafe { Fl_SVG_File_Surface_origin(self.inner, x, y) }
208    }
209
210    /// Returns the width and height of the printable rect
211    pub fn printable_rect(&self) -> (i32, i32) {
212        unsafe {
213            let mut x = 0;
214            let mut y = 0;
215            Fl_SVG_File_Surface_printable_rect(self.inner, &mut x, &mut y);
216            (x, y)
217        }
218    }
219
220    /// Draw a widget in an svg file surface.
221    /// The .svg file is not complete until the destructor was run
222    pub fn draw<W: WidgetExt>(&self, widget: &W, delta_x: i32, delta_y: i32) {
223        unsafe {
224            Fl_SVG_File_Surface_draw(
225                self.inner,
226                widget.as_widget_ptr() as *mut _,
227                delta_x,
228                delta_y,
229            );
230        }
231    }
232
233    /// draw a decorated window
234    pub fn draw_decorated_window<W: WindowExt>(&self, win: &W, x_offset: i32, y_offset: i32) {
235        unsafe {
236            Fl_SVG_File_Surface_draw_decorated_window(
237                self.inner,
238                win.as_widget_ptr() as *mut _,
239                x_offset,
240                y_offset,
241            );
242        }
243    }
244}
245
246impl Drop for SvgFileSurface {
247    fn drop(&mut self) {
248        unsafe { Fl_SVG_File_Surface_delete(self.inner) }
249    }
250}