gdk_pixbuf/
pixbuf_animation_iter.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::time::{Duration, SystemTime};
4
5use glib::translate::*;
6
7use super::{ffi, Pixbuf};
8
9glib::wrapper! {
10    /// An opaque object representing an iterator which points to a
11    /// certain position in an animation.
12    #[doc(alias = "GdkPixbufAnimationIter")]
13    pub struct PixbufAnimationIter(Object<ffi::GdkPixbufAnimationIter, ffi::GdkPixbufAnimationIterClass>);
14
15    match fn {
16        type_ => || ffi::gdk_pixbuf_animation_iter_get_type(),
17    }
18}
19
20impl PixbufAnimationIter {
21    /// Possibly advances an animation to a new frame.
22    ///
23    /// Chooses the frame based on the start time passed to
24    /// gdk_pixbuf_animation_get_iter().
25    ///
26    /// @current_time would normally come from g_get_current_time(), and
27    /// must be greater than or equal to the time passed to
28    /// gdk_pixbuf_animation_get_iter(), and must increase or remain
29    /// unchanged each time gdk_pixbuf_animation_iter_get_pixbuf() is
30    /// called. That is, you can't go backward in time; animations only
31    /// play forward.
32    ///
33    /// As a shortcut, pass `NULL` for the current time and g_get_current_time()
34    /// will be invoked on your behalf. So you only need to explicitly pass
35    /// @current_time if you're doing something odd like playing the animation
36    /// at double speed.
37    ///
38    /// If this function returns `FALSE`, there's no need to update the animation
39    /// display, assuming the display had been rendered prior to advancing;
40    /// if `TRUE`, you need to call gdk_pixbuf_animation_iter_get_pixbuf()
41    /// and update the display with the new pixbuf.
42    /// ## `current_time`
43    /// current time
44    ///
45    /// # Returns
46    ///
47    /// `TRUE` if the image may need updating
48    #[doc(alias = "gdk_pixbuf_animation_iter_advance")]
49    pub fn advance(&self, current_time: SystemTime) -> bool {
50        let diff = current_time
51            .duration_since(SystemTime::UNIX_EPOCH)
52            .expect("failed to convert time");
53
54        unsafe {
55            from_glib(ffi::gdk_pixbuf_animation_iter_advance(
56                self.to_glib_none().0,
57                &glib::ffi::GTimeVal {
58                    tv_sec: diff.as_secs() as _,
59                    tv_usec: diff.subsec_micros() as _,
60                },
61            ))
62        }
63    }
64
65    /// Gets the current pixbuf which should be displayed.
66    ///
67    /// The pixbuf might not be the same size as the animation itself
68    /// (gdk_pixbuf_animation_get_width(), gdk_pixbuf_animation_get_height()).
69    ///
70    /// This pixbuf should be displayed for gdk_pixbuf_animation_iter_get_delay_time()
71    /// milliseconds.
72    ///
73    /// The caller of this function does not own a reference to the returned
74    /// pixbuf; the returned pixbuf will become invalid when the iterator
75    /// advances to the next frame, which may happen anytime you call
76    /// gdk_pixbuf_animation_iter_advance().
77    ///
78    /// Copy the pixbuf to keep it (don't just add a reference), as it may get
79    /// recycled as you advance the iterator.
80    ///
81    /// # Returns
82    ///
83    /// the pixbuf to be displayed
84    #[doc(alias = "gdk_pixbuf_animation_iter_get_pixbuf")]
85    #[doc(alias = "get_pixbuf")]
86    pub fn pixbuf(&self) -> Pixbuf {
87        unsafe {
88            from_glib_none(ffi::gdk_pixbuf_animation_iter_get_pixbuf(
89                self.to_glib_none().0,
90            ))
91        }
92    }
93
94    /// Gets the number of milliseconds the current pixbuf should be displayed,
95    /// or -1 if the current pixbuf should be displayed forever.
96    ///
97    /// The `g_timeout_add()` function conveniently takes a timeout in milliseconds,
98    /// so you can use a timeout to schedule the next update.
99    ///
100    /// Note that some formats, like GIF, might clamp the timeout values in the
101    /// image file to avoid updates that are just too quick. The minimum timeout
102    /// for GIF images is currently 20 milliseconds.
103    ///
104    /// # Returns
105    ///
106    /// delay time in milliseconds (thousandths of a second)
107    #[doc(alias = "gdk_pixbuf_animation_iter_get_delay_time")]
108    #[doc(alias = "get_delay_time")]
109    pub fn delay_time(&self) -> Option<Duration> {
110        unsafe {
111            let res = ffi::gdk_pixbuf_animation_iter_get_delay_time(self.to_glib_none().0);
112
113            if res < 0 {
114                None
115            } else {
116                Some(Duration::from_millis(res as u64))
117            }
118        }
119    }
120
121    /// Used to determine how to respond to the area_updated signal on
122    /// #GdkPixbufLoader when loading an animation.
123    ///
124    /// The `::area_updated` signal is emitted for an area of the frame currently
125    /// streaming in to the loader. So if you're on the currently loading frame,
126    /// you will need to redraw the screen for the updated area.
127    ///
128    /// # Returns
129    ///
130    /// `TRUE` if the frame we're on is partially loaded, or the last frame
131    #[doc(alias = "gdk_pixbuf_animation_iter_on_currently_loading_frame")]
132    pub fn on_currently_loading_frame(&self) -> bool {
133        unsafe {
134            from_glib(ffi::gdk_pixbuf_animation_iter_on_currently_loading_frame(
135                self.to_glib_none().0,
136            ))
137        }
138    }
139}