Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.16 backports #837

Merged
merged 7 commits into from Nov 27, 2022
2 changes: 2 additions & 0 deletions gdk-pixbuf/src/lib.rs
Expand Up @@ -11,6 +11,8 @@ pub use glib;
#[allow(unused_imports)]
mod auto;

pub mod subclass;

mod pixbuf;
mod pixbuf_animation;
mod pixbuf_animation_iter;
Expand Down
2 changes: 1 addition & 1 deletion gdk-pixbuf/src/pixbuf_animation_iter.rs
Expand Up @@ -7,7 +7,7 @@ use std::time::SystemTime;

glib::wrapper! {
#[doc(alias = "GdkPixbufAnimationIter")]
pub struct PixbufAnimationIter(Object<ffi::GdkPixbufAnimationIter>);
pub struct PixbufAnimationIter(Object<ffi::GdkPixbufAnimationIter, ffi::GdkPixbufAnimationIterClass>);

match fn {
type_ => || ffi::gdk_pixbuf_animation_iter_get_type(),
Expand Down
17 changes: 17 additions & 0 deletions gdk-pixbuf/src/subclass/mod.rs
@@ -0,0 +1,17 @@
// Take a look at the license at the top of the repository in the LICENSE file.

// rustdoc-stripper-ignore-next
//! Traits intended for creating custom types.

pub mod pixbuf_animation;
pub mod pixbuf_animation_iter;
pub mod pixbuf_loader;

pub mod prelude {
pub use gio::subclass::prelude::*;
pub use glib::subclass::prelude::*;

pub use super::pixbuf_animation::{PixbufAnimationImpl, PixbufAnimationImplExt};
pub use super::pixbuf_animation_iter::{PixbufAnimationIterImpl, PixbufAnimationIterImplExt};
pub use super::pixbuf_loader::{PixbufLoaderImpl, PixbufLoaderImplExt};
}
170 changes: 170 additions & 0 deletions gdk-pixbuf/src/subclass/pixbuf_animation.rs
@@ -0,0 +1,170 @@
// Take a look at the license at the top of the repository in the LICENSE file.

// rustdoc-stripper-ignore-next
//! Traits intended for subclassing [`PixbufAnimation`](crate::PixbufAnimation).

use std::mem::MaybeUninit;
use std::time::Duration;

use crate::{Pixbuf, PixbufAnimation, PixbufAnimationIter};
use glib::subclass::prelude::*;
use glib::translate::*;
use glib::Cast;

pub trait PixbufAnimationImpl: ObjectImpl {
fn is_static_image(&self) -> bool {
self.parent_is_static_image()
}

fn static_image(&self) -> Option<Pixbuf> {
self.parent_static_image()
}

fn size(&self) -> (i32, i32) {
self.parent_size()
}

fn iter(&self, start_time: Duration) -> PixbufAnimationIter {
self.parent_iter(start_time)
}
}

pub trait PixbufAnimationImplExt: ObjectSubclass {
fn parent_is_static_image(&self) -> bool;
fn parent_static_image(&self) -> Option<Pixbuf>;
fn parent_size(&self) -> (i32, i32);
fn parent_iter(&self, start_time: Duration) -> PixbufAnimationIter;
}

impl<T: PixbufAnimationImpl> PixbufAnimationImplExt for T {
fn parent_is_static_image(&self) -> bool {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
let f = (*parent_class)
.is_static_image
.expect("No parent class implementation for \"is_static_image\"");

from_glib(f(self
.obj()
.unsafe_cast_ref::<PixbufAnimation>()
.to_glib_none()
.0))
}
}

fn parent_static_image(&self) -> Option<Pixbuf> {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
let f = (*parent_class)
.get_static_image
.expect("No parent class implementation for \"get_static_image\"");

from_glib_none(f(self
.obj()
.unsafe_cast_ref::<PixbufAnimation>()
.to_glib_none()
.0))
}
}

fn parent_size(&self) -> (i32, i32) {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
let f = (*parent_class)
.get_size
.expect("No parent class implementation for \"get_size\"");
let mut width = MaybeUninit::uninit();
let mut height = MaybeUninit::uninit();
f(
self.obj()
.unsafe_cast_ref::<PixbufAnimation>()
.to_glib_none()
.0,
width.as_mut_ptr(),
height.as_mut_ptr(),
);
(width.assume_init(), height.assume_init())
}
}

fn parent_iter(&self, start_time: Duration) -> PixbufAnimationIter {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
let f = (*parent_class)
.get_iter
.expect("No parent class implementation for \"get_iter\"");

let time = glib::ffi::GTimeVal {
tv_sec: start_time.as_secs() as _,
tv_usec: start_time.subsec_micros() as _,
};
from_glib_full(f(
self.obj()
.unsafe_cast_ref::<PixbufAnimation>()
.to_glib_none()
.0,
&time as *const _,
))
}
}
}

unsafe impl<T: PixbufAnimationImpl> IsSubclassable<T> for PixbufAnimation {
fn class_init(class: &mut ::glib::Class<Self>) {
Self::parent_class_init::<T>(class);

let klass = class.as_mut();
klass.get_static_image = Some(animation_get_static_image::<T>);
klass.get_size = Some(animation_get_size::<T>);
klass.get_iter = Some(animation_get_iter::<T>);
klass.is_static_image = Some(animation_is_static_image::<T>);
}
}

unsafe extern "C" fn animation_is_static_image<T: PixbufAnimationImpl>(
ptr: *mut ffi::GdkPixbufAnimation,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

imp.is_static_image().into_glib()
}

unsafe extern "C" fn animation_get_size<T: PixbufAnimationImpl>(
ptr: *mut ffi::GdkPixbufAnimation,
width_ptr: *mut libc::c_int,
height_ptr: *mut libc::c_int,
) {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

let (width, height) = imp.size();
*width_ptr = width;
*height_ptr = height;
}

unsafe extern "C" fn animation_get_static_image<T: PixbufAnimationImpl>(
ptr: *mut ffi::GdkPixbufAnimation,
) -> *mut ffi::GdkPixbuf {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

imp.static_image().to_glib_none().0
}

unsafe extern "C" fn animation_get_iter<T: PixbufAnimationImpl>(
ptr: *mut ffi::GdkPixbufAnimation,
start_time_ptr: *const glib::ffi::GTimeVal,
) -> *mut ffi::GdkPixbufAnimationIter {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

let total = Duration::from_secs((*start_time_ptr).tv_sec.try_into().unwrap())
+ Duration::from_micros((*start_time_ptr).tv_usec.try_into().unwrap());

imp.iter(total).to_glib_full()
}
172 changes: 172 additions & 0 deletions gdk-pixbuf/src/subclass/pixbuf_animation_iter.rs
@@ -0,0 +1,172 @@
// Take a look at the license at the top of the repository in the LICENSE file.

// rustdoc-stripper-ignore-next
//! Traits intended for subclassing [`PixbufAnimationIter`](crate::PixbufAnimationIter).

use std::time::Duration;

use glib::subclass::prelude::*;
use glib::translate::*;
use glib::Cast;

use crate::{Pixbuf, PixbufAnimationIter};

pub trait PixbufAnimationIterImpl: ObjectImpl {
// rustdoc-stripper-ignore-next
/// Time in milliseconds, returning `None` implies showing the same pixbuf forever.
fn delay_time(&self) -> Option<Duration> {
self.parent_delay_time()
}

fn pixbuf(&self) -> Pixbuf {
self.parent_pixbuf()
}

fn on_currently_loading_frame(&self) -> bool {
self.parent_on_currently_loading_frame()
}

fn advance(&self, time: Duration) -> bool {
self.parent_advance(time)
}
}

pub trait PixbufAnimationIterImplExt: ObjectSubclass {
fn parent_delay_time(&self) -> Option<Duration>;
fn parent_pixbuf(&self) -> Pixbuf;
fn parent_on_currently_loading_frame(&self) -> bool;
fn parent_advance(&self, time: Duration) -> bool;
}

impl<T: PixbufAnimationIterImpl> PixbufAnimationIterImplExt for T {
fn parent_delay_time(&self) -> Option<Duration> {
unsafe {
let data = T::type_data();
let parent_class =
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
let f = (*parent_class)
.get_delay_time
.expect("No parent class implementation for \"get_delay_time\"");

let time = f(self
.obj()
.unsafe_cast_ref::<PixbufAnimationIter>()
.to_glib_none()
.0);
if time == -1 {
None
} else {
Some(Duration::from_millis(time.try_into().unwrap()))
}
}
}

fn parent_pixbuf(&self) -> Pixbuf {
unsafe {
let data = T::type_data();
let parent_class =
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
let f = (*parent_class)
.get_pixbuf
.expect("No parent class implementation for \"get_pixbuf\"");

from_glib_none(f(self
.obj()
.unsafe_cast_ref::<PixbufAnimationIter>()
.to_glib_none()
.0))
}
}

fn parent_on_currently_loading_frame(&self) -> bool {
unsafe {
let data = T::type_data();
let parent_class =
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
let f = (*parent_class)
.on_currently_loading_frame
.expect("No parent class implementation for \"on_currently_loading_frame\"");

from_glib(f(self
.obj()
.unsafe_cast_ref::<PixbufAnimationIter>()
.to_glib_none()
.0))
}
}

fn parent_advance(&self, time: Duration) -> bool {
unsafe {
let data = T::type_data();
let parent_class =
data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationIterClass;
let f = (*parent_class)
.advance
.expect("No parent class implementation for \"advance\"");

let time = glib::ffi::GTimeVal {
tv_sec: time.as_secs() as _,
tv_usec: time.subsec_micros() as _,
};
from_glib(f(
self.obj()
.unsafe_cast_ref::<PixbufAnimationIter>()
.to_glib_none()
.0,
&time as *const _,
))
}
}
}

unsafe impl<T: PixbufAnimationIterImpl> IsSubclassable<T> for PixbufAnimationIter {
fn class_init(class: &mut ::glib::Class<Self>) {
Self::parent_class_init::<T>(class);

let klass = class.as_mut();
klass.get_delay_time = Some(animation_iter_get_delay_time::<T>);
klass.get_pixbuf = Some(animation_iter_get_pixbuf::<T>);
klass.on_currently_loading_frame = Some(animation_iter_on_currently_loading_frame::<T>);
klass.advance = Some(animation_iter_advance::<T>);
}
}

unsafe extern "C" fn animation_iter_get_delay_time<T: PixbufAnimationIterImpl>(
ptr: *mut ffi::GdkPixbufAnimationIter,
) -> i32 {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

imp.delay_time().map(|t| t.as_millis() as i32).unwrap_or(-1)
}

unsafe extern "C" fn animation_iter_get_pixbuf<T: PixbufAnimationIterImpl>(
ptr: *mut ffi::GdkPixbufAnimationIter,
) -> *mut ffi::GdkPixbuf {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

imp.pixbuf().to_glib_none().0
}

unsafe extern "C" fn animation_iter_on_currently_loading_frame<T: PixbufAnimationIterImpl>(
ptr: *mut ffi::GdkPixbufAnimationIter,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

imp.on_currently_loading_frame().into_glib()
}

unsafe extern "C" fn animation_iter_advance<T: PixbufAnimationIterImpl>(
ptr: *mut ffi::GdkPixbufAnimationIter,
time_ptr: *const glib::ffi::GTimeVal,
) -> glib::ffi::gboolean {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.imp();

let total = Duration::from_secs((*time_ptr).tv_sec.try_into().unwrap())
+ Duration::from_micros((*time_ptr).tv_usec.try_into().unwrap());

imp.advance(total).into_glib()
}