1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
pub use crate::prelude::*;
use fltk_sys::surface::*;
use std::ffi::CString;
use std::path;

/// An image surface object.
/// Example usage:
/// ```no_run
/// use fltk::*;
/// let but = button::Button::new(0, 0, 80, 40, "Click");
/// let sur = surface::ImageSurface::new(but.width(), but.height(), false);
/// surface::ImageSurface::push_current(&sur);
/// draw::set_draw_color(Color::White);
/// draw::draw_rectf(0, 0, but.width(), but.height());
/// sur.draw(&but, 0, 0);
/// let img = sur.image().unwrap();
/// surface::ImageSurface::pop_current();
/// ```
pub struct ImageSurface {
    _inner: *mut Fl_Image_Surface,
}

impl SurfaceDevice for ImageSurface {
    fn is_current(&self) -> bool {
        unsafe { Fl_Surface_Device_is_current(self._inner as *mut _) != 0 }
    }

    fn surface() -> Self {
        unsafe {
            let ptr = Fl_Surface_Device_surface();
            assert!(!ptr.is_null());
            Self {
                _inner: ptr as *mut _,
            }
        }
    }

    fn push_current(new_current: &ImageSurface) {
        unsafe { Fl_Surface_Device_push_current(new_current._inner as *mut _) }
    }

    fn pop_current() {
        unsafe {
            Fl_Surface_Device_pop_current();
        }
    }
}

impl ImageSurface {
    /// Creates a new image surface
    pub fn new(w: i32, h: i32, high_res: bool) -> ImageSurface {
        unsafe {
            let ptr = Fl_Image_Surface_new(w, h, high_res as i32);
            assert!(!ptr.is_null());
            ImageSurface { _inner: ptr }
        }
    }

    /// Gets the image of an image surface as an rgb image
    pub fn image(&self) -> Option<crate::image::RgbImage> {
        unsafe {
            let ptr = Fl_Image_Surface_image(self._inner);
            if ptr.is_null() {
                None
            } else {
                Some(crate::image::RgbImage::from_image_ptr(ptr as *mut _))
            }
        }
    }

    /// Gets the high resolution image of an image surface as a shared image
    pub fn highres_image(&self) -> Option<crate::image::SharedImage> {
        unsafe {
            let ptr = Fl_Image_Surface_highres_image(self._inner);
            if ptr.is_null() {
                None
            } else {
                Some(crate::image::SharedImage::from_image_ptr(ptr as *mut _))
            }
        }
    }

    /// Gets the origin coordinates of an image surface
    pub fn origin(&self) -> (i32, i32) {
        unsafe {
            let mut x = 0;
            let mut y = 0;
            Fl_Image_Surface_origin(self._inner, &mut x, &mut y);
            (x, y)
        }
    }

    /// Set the origin coordinates of an image surface
    pub fn set_origin(&mut self, x: i32, y: i32) {
        unsafe { Fl_Image_Surface_set_origin(self._inner, x, y) }
    }

    /// Rescale an image surface
    pub fn rescale(&mut self) {
        unsafe { Fl_Image_Surface_rescale(self._inner) }
    }

    /// Draw a widget on the image surface
    pub fn draw<W: WidgetExt>(&self, widget: &W, delta_x: i32, delta_y: i32) {
        unsafe {
            Fl_Image_Surface_draw(
                self._inner,
                widget.as_widget_ptr() as *mut _,
                delta_x,
                delta_y,
            )
        }
    }

    /// draw a decorated window
    pub fn draw_decorated_window<W: WindowExt>(&self, win: &W, x_offset: i32, y_offset: i32) {
        unsafe {
            Fl_Image_Surface_draw_decorated_window(
                self._inner,
                win.as_widget_ptr() as *mut _,
                x_offset,
                y_offset,
            )
        }
    }
}

impl Drop for ImageSurface {
    fn drop(&mut self) {
        unsafe { Fl_Image_Surface_delete(self._inner) }
    }
}

/// An SVG image surface object
/// Example usage:
/// ```no_run
/// use fltk::*;
/// let but = button::Button::new(0, 0, 80, 40, "Click");
/// // We need the destructor of SvgFileSurface to actually create the image
/// {
///     let sur = surface::SvgFileSurface::new(but.width(), but.height(), "temp.svg");
///     surface::SvgFileSurface::push_current(&sur);
///     draw::set_draw_color(Color::White);
///     draw::draw_rectf(0, 0, but.width(), but.height());
///     sur.draw(&but, 0, 0);
///     surface::SvgFileSurface::pop_current();
/// }
/// ```
pub struct SvgFileSurface {
    _inner: *mut Fl_SVG_File_Surface,
}

impl SurfaceDevice for SvgFileSurface {
    fn is_current(&self) -> bool {
        unsafe { Fl_Surface_Device_is_current(self._inner as *mut _) != 0 }
    }

    fn surface() -> Self {
        unsafe {
            let ptr = Fl_Surface_Device_surface();
            assert!(!ptr.is_null());
            Self {
                _inner: ptr as *mut _,
            }
        }
    }

    fn push_current(new_current: &SvgFileSurface) {
        unsafe { Fl_Surface_Device_push_current(new_current._inner as *mut _) }
    }

    fn pop_current() {
        unsafe {
            Fl_Surface_Device_pop_current();
        }
    }
}

impl SvgFileSurface {
    /// Returns a new SvgFileSurface
    pub fn new<P: AsRef<path::Path>>(width: i32, height: i32, path: P) -> SvgFileSurface {
        let path = CString::safe_new(path.as_ref().to_str().unwrap());
        unsafe {
            let ptr = Fl_SVG_File_Surface_new(width, height, path.as_ptr());
            assert!(!ptr.is_null());
            SvgFileSurface { _inner: ptr }
        }
    }

    /// Sets the origin of the SvgFileSurface
    pub fn set_origin(&mut self, x: i32, y: i32) {
        unsafe { Fl_SVG_File_Surface_origin(self._inner, x, y) }
    }

    /// Returns the width and height of the printable rect
    pub fn printable_rect(&self) -> (i32, i32) {
        unsafe {
            let mut x = 0;
            let mut y = 0;
            Fl_SVG_File_Surface_printable_rect(self._inner, &mut x, &mut y);
            (x, y)
        }
    }

    /// Draw a widget in an svg file surface
    /// the .svg file is not complete until the destructor was run
    pub fn draw<W: WidgetExt>(&self, widget: &W, delta_x: i32, delta_y: i32) {
        unsafe {
            Fl_SVG_File_Surface_draw(
                self._inner,
                widget.as_widget_ptr() as *mut _,
                delta_x,
                delta_y,
            )
        }
    }

    /// draw a decorated window
    pub fn draw_decorated_window<W: WindowExt>(&self, win: &W, x_offset: i32, y_offset: i32) {
        unsafe {
            Fl_SVG_File_Surface_draw_decorated_window(
                self._inner,
                win.as_widget_ptr() as *mut _,
                x_offset,
                y_offset,
            )
        }
    }
}

impl Drop for SvgFileSurface {
    fn drop(&mut self) {
        unsafe { Fl_SVG_File_Surface_delete(self._inner) }
    }
}