Skip to content

Commit

Permalink
Merge pull request #837 from sdroege/0.16-backports
Browse files Browse the repository at this point in the history
0.16 backports
  • Loading branch information
sdroege committed Nov 27, 2022
2 parents a47feaf + 27dda71 commit 6e69c8c
Show file tree
Hide file tree
Showing 10 changed files with 520 additions and 4 deletions.
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()
}

0 comments on commit 6e69c8c

Please sign in to comment.