Skip to content

Commit 93e36b8

Browse files
gdk-pixbuf: Add PixbufAnimation subclassing support
1 parent 6653861 commit 93e36b8

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

gdk-pixbuf/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub use glib;
1111
#[allow(unused_imports)]
1212
mod auto;
1313

14+
pub mod subclass;
15+
1416
mod pixbuf;
1517
mod pixbuf_animation;
1618
mod pixbuf_animation_iter;

gdk-pixbuf/src/subclass/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
// rustdoc-stripper-ignore-next
4+
//! Traits intended for creating custom types.
5+
6+
pub mod pixbuf_animation;
7+
8+
pub mod prelude {
9+
pub use gio::subclass::prelude::*;
10+
pub use glib::subclass::prelude::*;
11+
12+
pub use super::pixbuf_animation::{PixbufAnimationImpl, PixbufAnimationImplExt};
13+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
// rustdoc-stripper-ignore-next
4+
//! Traits intended for subclassing [`PixbufAnimation`](crate::PixbufAnimation).
5+
6+
use std::mem::MaybeUninit;
7+
use std::time::Duration;
8+
9+
use crate::{Pixbuf, PixbufAnimation, PixbufAnimationIter};
10+
use glib::subclass::prelude::*;
11+
use glib::translate::*;
12+
use glib::Cast;
13+
14+
pub trait PixbufAnimationImpl: ObjectImpl {
15+
fn is_static_image(&self) -> bool {
16+
self.parent_is_static_image()
17+
}
18+
19+
fn static_image(&self) -> Option<Pixbuf> {
20+
self.parent_static_image()
21+
}
22+
23+
fn size(&self) -> (i32, i32) {
24+
self.parent_size()
25+
}
26+
27+
fn iter(&self, start_time: Duration) -> PixbufAnimationIter {
28+
self.parent_iter(start_time)
29+
}
30+
}
31+
32+
pub trait PixbufAnimationImplExt: ObjectSubclass {
33+
fn parent_is_static_image(&self) -> bool;
34+
fn parent_static_image(&self) -> Option<Pixbuf>;
35+
fn parent_size(&self) -> (i32, i32);
36+
fn parent_iter(&self, start_time: Duration) -> PixbufAnimationIter;
37+
}
38+
39+
impl<T: PixbufAnimationImpl> PixbufAnimationImplExt for T {
40+
fn parent_is_static_image(&self) -> bool {
41+
unsafe {
42+
let data = T::type_data();
43+
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
44+
let f = (*parent_class)
45+
.is_static_image
46+
.expect("No parent class implementation for \"is_static_image\"");
47+
48+
from_glib(f(self
49+
.obj()
50+
.unsafe_cast_ref::<PixbufAnimation>()
51+
.to_glib_none()
52+
.0))
53+
}
54+
}
55+
56+
fn parent_static_image(&self) -> Option<Pixbuf> {
57+
unsafe {
58+
let data = T::type_data();
59+
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
60+
let f = (*parent_class)
61+
.get_static_image
62+
.expect("No parent class implementation for \"get_static_image\"");
63+
64+
from_glib_none(f(self
65+
.obj()
66+
.unsafe_cast_ref::<PixbufAnimation>()
67+
.to_glib_none()
68+
.0))
69+
}
70+
}
71+
72+
fn parent_size(&self) -> (i32, i32) {
73+
unsafe {
74+
let data = T::type_data();
75+
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
76+
let f = (*parent_class)
77+
.get_size
78+
.expect("No parent class implementation for \"get_size\"");
79+
let mut width = MaybeUninit::uninit();
80+
let mut height = MaybeUninit::uninit();
81+
f(
82+
self.obj()
83+
.unsafe_cast_ref::<PixbufAnimation>()
84+
.to_glib_none()
85+
.0,
86+
width.as_mut_ptr(),
87+
height.as_mut_ptr(),
88+
);
89+
(width.assume_init(), height.assume_init())
90+
}
91+
}
92+
93+
fn parent_iter(&self, start_time: Duration) -> PixbufAnimationIter {
94+
unsafe {
95+
let data = T::type_data();
96+
let parent_class = data.as_ref().parent_class() as *mut ffi::GdkPixbufAnimationClass;
97+
let f = (*parent_class)
98+
.get_iter
99+
.expect("No parent class implementation for \"get_iter\"");
100+
101+
let time = glib::ffi::GTimeVal {
102+
tv_sec: start_time.as_secs() as _,
103+
tv_usec: start_time.subsec_micros() as _,
104+
};
105+
from_glib_full(f(
106+
self.obj()
107+
.unsafe_cast_ref::<PixbufAnimation>()
108+
.to_glib_none()
109+
.0,
110+
&time as *const _,
111+
))
112+
}
113+
}
114+
}
115+
116+
unsafe impl<T: PixbufAnimationImpl> IsSubclassable<T> for PixbufAnimation {
117+
fn class_init(class: &mut ::glib::Class<Self>) {
118+
Self::parent_class_init::<T>(class);
119+
120+
let klass = class.as_mut();
121+
klass.get_static_image = Some(animation_get_static_image::<T>);
122+
klass.get_size = Some(animation_get_size::<T>);
123+
klass.get_iter = Some(animation_get_iter::<T>);
124+
klass.is_static_image = Some(animation_is_static_image::<T>);
125+
}
126+
}
127+
128+
unsafe extern "C" fn animation_is_static_image<T: PixbufAnimationImpl>(
129+
ptr: *mut ffi::GdkPixbufAnimation,
130+
) -> glib::ffi::gboolean {
131+
let instance = &*(ptr as *mut T::Instance);
132+
let imp = instance.imp();
133+
134+
imp.is_static_image().into_glib()
135+
}
136+
137+
unsafe extern "C" fn animation_get_size<T: PixbufAnimationImpl>(
138+
ptr: *mut ffi::GdkPixbufAnimation,
139+
width_ptr: *mut libc::c_int,
140+
height_ptr: *mut libc::c_int,
141+
) {
142+
let instance = &*(ptr as *mut T::Instance);
143+
let imp = instance.imp();
144+
145+
let (width, height) = imp.size();
146+
*width_ptr = width;
147+
*height_ptr = height;
148+
}
149+
150+
unsafe extern "C" fn animation_get_static_image<T: PixbufAnimationImpl>(
151+
ptr: *mut ffi::GdkPixbufAnimation,
152+
) -> *mut ffi::GdkPixbuf {
153+
let instance = &*(ptr as *mut T::Instance);
154+
let imp = instance.imp();
155+
156+
imp.static_image().to_glib_none().0
157+
}
158+
159+
unsafe extern "C" fn animation_get_iter<T: PixbufAnimationImpl>(
160+
ptr: *mut ffi::GdkPixbufAnimation,
161+
start_time_ptr: *const glib::ffi::GTimeVal,
162+
) -> *mut ffi::GdkPixbufAnimationIter {
163+
let instance = &*(ptr as *mut T::Instance);
164+
let imp = instance.imp();
165+
166+
let total = Duration::from_secs((*start_time_ptr).tv_sec.try_into().unwrap())
167+
+ Duration::from_micros((*start_time_ptr).tv_usec.try_into().unwrap());
168+
169+
imp.iter(total).to_glib_full()
170+
}

0 commit comments

Comments
 (0)