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
// Take a look at the license at the top of the repository in the LICENSE file. use super::Pixbuf; use glib::translate::*; use std::time::SystemTime; glib::wrapper! { /// An opaque struct representing an iterator which points to a /// certain position in an animation. #[doc(alias = "GdkPixbufAnimationIter")] pub struct PixbufAnimationIter(Object<ffi::GdkPixbufAnimationIter>); match fn { type_ => || ffi::gdk_pixbuf_animation_iter_get_type(), } } impl PixbufAnimationIter { /// Possibly advances an animation to a new frame. Chooses the frame based /// on the start time passed to [`PixbufAnimationExtManual::iter()`][crate::prelude::PixbufAnimationExtManual::iter()]. /// /// `current_time` would normally come from `g_get_current_time()`, and /// must be greater than or equal to the time passed to /// [`PixbufAnimationExtManual::iter()`][crate::prelude::PixbufAnimationExtManual::iter()], and must increase or remain /// unchanged each time [`PixbufAnimationIterExtManual::pixbuf()`][crate::prelude::PixbufAnimationIterExtManual::pixbuf()] is /// called. That is, you can't go backward in time; animations only /// play forward. /// /// As a shortcut, pass [`None`] for the current time and `g_get_current_time()` /// will be invoked on your behalf. So you only need to explicitly pass /// `current_time` if you're doing something odd like playing the animation /// at double speed. /// /// If this function returns [`false`], there's no need to update the animation /// display, assuming the display had been rendered prior to advancing; /// if [`true`], you need to call [`PixbufAnimationIterExtManual::pixbuf()`][crate::prelude::PixbufAnimationIterExtManual::pixbuf()] /// and update the display with the new pixbuf. /// ## `current_time` /// current time /// /// # Returns /// /// [`true`] if the image may need updating #[doc(alias = "gdk_pixbuf_animation_iter_advance")] pub fn advance(&self, start_time: SystemTime) -> bool { let diff = start_time .duration_since(SystemTime::UNIX_EPOCH) .expect("failed to convert time"); unsafe { from_glib(ffi::gdk_pixbuf_animation_iter_advance( self.to_glib_none().0, &glib::ffi::GTimeVal { tv_sec: diff.as_secs() as _, tv_usec: diff.subsec_micros() as _, }, )) } } /// Gets the current pixbuf which should be displayed; the pixbuf might not /// be the same size as the animation itself /// ([`PixbufAnimationExt::width()`][crate::prelude::PixbufAnimationExt::width()], [`PixbufAnimationExt::height()`][crate::prelude::PixbufAnimationExt::height()]). /// This pixbuf should be displayed for /// [`PixbufAnimationIterExtManual::delay_time()`][crate::prelude::PixbufAnimationIterExtManual::delay_time()] milliseconds. The caller /// of this function does not own a reference to the returned pixbuf; /// the returned pixbuf will become invalid when the iterator advances /// to the next frame, which may happen anytime you call /// [`PixbufAnimationIterExtManual::advance()`][crate::prelude::PixbufAnimationIterExtManual::advance()]. Copy the pixbuf to keep it /// (don't just add a reference), as it may get recycled as you advance /// the iterator. /// /// # Returns /// /// the pixbuf to be displayed #[doc(alias = "gdk_pixbuf_animation_iter_get_pixbuf")] #[doc(alias = "get_pixbuf")] pub fn pixbuf(&self) -> Pixbuf { unsafe { from_glib_none(ffi::gdk_pixbuf_animation_iter_get_pixbuf( self.to_glib_none().0, )) } } /// Gets the number of milliseconds the current pixbuf should be displayed, /// or -1 if the current pixbuf should be displayed forever. `g_timeout_add()` /// conveniently takes a timeout in milliseconds, so you can use a timeout /// to schedule the next update. /// /// Note that some formats, like GIF, might clamp the timeout values in the /// image file to avoid updates that are just too quick. The minimum timeout /// for GIF images is currently 20 milliseconds. /// /// # Returns /// /// delay time in milliseconds (thousandths of a second) #[doc(alias = "gdk_pixbuf_animation_iter_get_delay_time")] #[doc(alias = "get_delay_time")] pub fn delay_time(&self) -> i32 { unsafe { ffi::gdk_pixbuf_animation_iter_get_delay_time(self.to_glib_none().0) } } /// Used to determine how to respond to the area_updated signal on /// [`PixbufLoader`][crate::PixbufLoader] when loading an animation. area_updated is emitted /// for an area of the frame currently streaming in to the loader. So if /// you're on the currently loading frame, you need to redraw the screen for /// the updated area. /// /// # Returns /// /// [`true`] if the frame we're on is partially loaded, or the last frame #[doc(alias = "gdk_pixbuf_animation_iter_on_currently_loading_frame")] pub fn on_currently_loading_frame(&self) -> bool { unsafe { from_glib(ffi::gdk_pixbuf_animation_iter_on_currently_loading_frame( self.to_glib_none().0, )) } } }