[librsvg: 12/30] c-api: update per subclassing changes
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 12/30] c-api: update per subclassing changes
- Date: Wed, 23 Jun 2021 23:05:39 +0000 (UTC)
commit 953d81fdc4f36f22ad119ba1ff86fd4253286d50
Author: Bilal Elmoussaoui <bil elmoussaoui gmail com>
Date: Thu Jun 17 13:37:46 2021 +0200
c-api: update per subclassing changes
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/516>
src/c_api/handle.rs | 491 ++++++++++++++++++++++++++++------------------------
1 file changed, 260 insertions(+), 231 deletions(-)
---
diff --git a/src/c_api/handle.rs b/src/c_api/handle.rs
index fd045934..ccd8d545 100644
--- a/src/c_api/handle.rs
+++ b/src/c_api/handle.rs
@@ -21,7 +21,6 @@
use std::cell::{Cell, Ref, RefCell, RefMut};
use std::ffi::{CStr, CString, OsStr};
use std::fmt;
-use std::ops;
use std::path::PathBuf;
use std::ptr;
use std::slice;
@@ -33,10 +32,9 @@ use gio::prelude::*;
use glib::error::ErrorDomain;
use url::Url;
-use glib::object::ObjectClass;
use glib::subclass::prelude::*;
use glib::translate::*;
-use glib::{Bytes, Cast, ParamFlags, ParamSpec, StaticType, ToValue, Type};
+use glib::{Bytes, Cast, ParamFlags, ParamSpec, StaticType, ToValue};
use once_cell::sync::Lazy;
use glib::types::instance_of;
@@ -146,6 +144,10 @@ pub struct RsvgHandleClass {
_abi_padding: [glib::ffi::gpointer; 15],
}
+unsafe impl ClassStruct for RsvgHandleClass {
+ type Type = imp::CHandle;
+}
+
/// GObject instance struct for RsvgHandle.
///
/// This is not done through [`glib::subclass::prelude::InstanceStruct<T>`] because we need
@@ -159,6 +161,10 @@ pub struct RsvgHandle {
_abi_padding: [glib::ffi::gpointer; 16],
}
+unsafe impl InstanceStruct for RsvgHandle {
+ type Type = imp::CHandle;
+}
+
/// State machine for `RsvgHandle`.
///
/// When an `RsvgHandled` is created it is empty / not loaded yet, and it does not know
@@ -273,217 +279,212 @@ impl From<RsvgRectangle> for cairo::Rectangle {
}
}
-/// Contains all the interior mutability for a RsvgHandle to be called
-/// from the C API.
-pub struct CHandle {
- inner: RefCell<CHandleInner>,
- load_state: RefCell<LoadState>,
-}
-
-struct CHandleInner {
- dpi: Dpi,
- load_flags: LoadFlags,
- base_url: BaseUrl,
- size_callback: SizeCallback,
- is_testing: bool,
-}
-
-unsafe impl ClassStruct for RsvgHandleClass {
- type Type = CHandle;
-}
-
-unsafe impl InstanceStruct for RsvgHandle {
- type Type = CHandle;
-}
-
-impl ops::Deref for RsvgHandleClass {
- type Target = ObjectClass;
-
- fn deref(&self) -> &Self::Target {
- unsafe {
- let self_ptr: *const RsvgHandleClass = self;
- &*(self_ptr as *const Self::Target)
+mod imp {
+ use super::*;
+ /// Contains all the interior mutability for a RsvgHandle to be called
+ /// from the C API.
+ pub struct CHandle {
+ pub(super) inner: RefCell<CHandleInner>,
+ pub(super) load_state: RefCell<LoadState>,
+ }
+
+ pub(super) struct CHandleInner {
+ pub(super) dpi: Dpi,
+ pub(super) load_flags: LoadFlags,
+ pub(super) base_url: BaseUrl,
+ pub(super) size_callback: SizeCallback,
+ pub(super) is_testing: bool,
+ }
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for CHandle {
+ const NAME: &'static str = "RsvgHandle";
+
+ type ParentType = glib::Object;
+ type Type = super::CHandle;
+
+ type Instance = RsvgHandle;
+ type Class = RsvgHandleClass;
+
+ fn new() -> Self {
+ CHandle {
+ inner: RefCell::new(CHandleInner {
+ dpi: Dpi::default(),
+ load_flags: LoadFlags::default(),
+ base_url: BaseUrl::default(),
+ size_callback: SizeCallback::default(),
+ is_testing: false,
+ }),
+ load_state: RefCell::new(LoadState::Start),
+ }
}
}
-}
-impl ops::DerefMut for RsvgHandleClass {
- fn deref_mut(&mut self) -> &mut Self::Target {
- unsafe {
- let self_ptr: *mut RsvgHandleClass = self;
- &mut *(self_ptr as *mut Self::Target)
+ impl ObjectImpl for CHandle {
+ fn properties() -> &'static [ParamSpec] {
+ static PROPERTIES: Lazy<Vec<ParamSpec>> = Lazy::new(|| {
+ vec![
+ ParamSpec::new_flags(
+ "flags",
+ "Flags",
+ "Loading flags",
+ HandleFlags::static_type(),
+ 0,
+ ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
+ ),
+ ParamSpec::new_double(
+ "dpi-x",
+ "Horizontal DPI",
+ "Horizontal resolution in dots per inch",
+ 0.0,
+ f64::MAX,
+ 0.0,
+ ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
+ ),
+ ParamSpec::new_double(
+ "dpi-y",
+ "Vertical DPI",
+ "Vertical resolution in dots per inch",
+ 0.0,
+ f64::MAX,
+ 0.0,
+ ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
+ ),
+ ParamSpec::new_string(
+ "base-uri",
+ "Base URI",
+ "Base URI for resolving relative references",
+ None,
+ ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
+ ),
+ ParamSpec::new_int(
+ "width",
+ "Image width",
+ "Image width",
+ 0,
+ i32::MAX,
+ 0,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_int(
+ "height",
+ "Image height",
+ "Image height",
+ 0,
+ i32::MAX,
+ 0,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_double(
+ "em",
+ "em",
+ "em",
+ 0.0,
+ f64::MAX,
+ 0.0,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_double(
+ "ex",
+ "ex",
+ "ex",
+ 0.0,
+ f64::MAX,
+ 0.0,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_string(
+ "title",
+ "deprecated",
+ "deprecated",
+ None,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_string(
+ "desc",
+ "deprecated",
+ "deprecated",
+ None,
+ ParamFlags::READABLE,
+ ),
+ ParamSpec::new_string(
+ "metadata",
+ "deprecated",
+ "deprecated",
+ None,
+ ParamFlags::READABLE,
+ ),
+ ]
+ });
+ PROPERTIES.as_ref()
}
- }
-}
-#[glib::object_subclass]
-impl ObjectSubclass for CHandle {
- const NAME: &'static str = "RsvgHandle";
+ fn set_property(
+ &self,
+ obj: &Self::Type,
+ id: usize,
+ value: &glib::Value,
+ pspec: &ParamSpec,
+ ) {
+ match pspec.name() {
+ "flags" => {
+ let v: HandleFlags = value.get().expect("flags value has incorrect type");
+ obj.set_flags(v);
+ }
- type ParentType = glib::Object;
+ "dpi-x" => {
+ let dpi_x: f64 = value.get().expect("dpi-x value has incorrect type");
+ obj.set_dpi_x(dpi_x);
+ }
- // We don't use subclass:simple::InstanceStruct and ClassStruct
- // because we need to maintain the respective _abi_padding of each
- // of RsvgHandleClass and RsvgHandle.
+ "dpi-y" => {
+ let dpi_y: f64 = value.get().expect("dpi-y value has incorrect type");
+ obj.set_dpi_y(dpi_y);
+ }
- type Instance = RsvgHandle;
- type Class = RsvgHandleClass;
-
- fn new() -> Self {
- CHandle {
- inner: RefCell::new(CHandleInner {
- dpi: Dpi::default(),
- load_flags: LoadFlags::default(),
- base_url: BaseUrl::default(),
- size_callback: SizeCallback::default(),
- is_testing: false,
- }),
- load_state: RefCell::new(LoadState::Start),
- }
- }
-}
+ "base-uri" => {
+ let v: Option<String> = value.get().expect("base-uri value has incorrect type");
-impl StaticType for CHandle {
- fn static_type() -> Type {
- CHandle::type_()
- }
-}
-
-impl ObjectImpl for CHandle {
- fn properties() -> &'static [ParamSpec] {
- static PROPERTIES: Lazy<Vec<ParamSpec>> = Lazy::new(|| {
- vec![
- ParamSpec::new_flags(
- "flags",
- "Flags",
- "Loading flags",
- HandleFlags::static_type(),
- 0,
- ParamFlags::READWRITE | ParamFlags::CONSTRUCT_ONLY,
- ),
- ParamSpec::new_double(
- "dpi-x",
- "Horizontal DPI",
- "Horizontal resolution in dots per inch",
- 0.0,
- f64::MAX,
- 0.0,
- ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
- ),
- ParamSpec::new_double(
- "dpi-y",
- "Vertical DPI",
- "Vertical resolution in dots per inch",
- 0.0,
- f64::MAX,
- 0.0,
- ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
- ),
- ParamSpec::new_string(
- "base-uri",
- "Base URI",
- "Base URI for resolving relative references",
- None,
- ParamFlags::READWRITE | ParamFlags::CONSTRUCT,
- ),
- ParamSpec::new_int(
- "width",
- "Image width",
- "Image width",
- 0,
- i32::MAX,
- 0,
- ParamFlags::READABLE,
- ),
- ParamSpec::new_int(
- "height",
- "Image height",
- "Image height",
- 0,
- i32::MAX,
- 0,
- ParamFlags::READABLE,
- ),
- ParamSpec::new_double("em", "em", "em", 0.0, f64::MAX, 0.0, ParamFlags::READABLE),
- ParamSpec::new_double("ex", "ex", "ex", 0.0, f64::MAX, 0.0, ParamFlags::READABLE),
- ParamSpec::new_string(
- "title",
- "deprecated",
- "deprecated",
- None,
- ParamFlags::READABLE,
- ),
- ParamSpec::new_string(
- "desc",
- "deprecated",
- "deprecated",
- None,
- ParamFlags::READABLE,
- ),
- ParamSpec::new_string(
- "metadata",
- "deprecated",
- "deprecated",
- None,
- ParamFlags::READABLE,
- ),
- ]
- });
- PROPERTIES.as_ref()
- }
-
- fn set_property(&self, _obj: &Self::Type, id: usize, value: &glib::Value, pspec: &ParamSpec) {
- match pspec.name() {
- "flags" => {
- let v: HandleFlags = value.get().expect("flags value has incorrect type");
- self.set_flags(v);
- }
+ // rsvg_handle_set_base_uri() expects non-NULL URI strings,
+ // but the "base-uri" property can be set to NULL due to a missing
+ // construct-time property.
- "dpi-x" => {
- let dpi_x: f64 = value.get().expect("dpi-x value has incorrect type");
- self.set_dpi_x(dpi_x);
- }
+ if let Some(s) = v {
+ obj.set_base_url(&s);
+ }
+ }
- "dpi-y" => {
- let dpi_y: f64 = value.get().expect("dpi-y value has incorrect type");
- self.set_dpi_y(dpi_y);
+ _ => unreachable!("invalid property id {}", id),
}
+ }
- "base-uri" => {
- let v: Option<String> = value.get().expect("base-uri value has incorrect type");
-
- // rsvg_handle_set_base_uri() expects non-NULL URI strings,
- // but the "base-uri" property can be set to NULL due to a missing
- // construct-time property.
-
- if let Some(s) = v {
- self.set_base_url(&s);
- }
+ fn property(&self, obj: &Self::Type, id: usize, pspec: &ParamSpec) -> glib::Value {
+ match pspec.name() {
+ "flags" => obj.get_flags().to_value(),
+ "dpi-x" => obj.get_dpi_x().to_value(),
+ "dpi-y" => obj.get_dpi_y().to_value(),
+ "base-uri" => obj.get_base_url().to_value(),
+ "width" => obj.get_dimensions_or_empty().width.to_value(),
+ "height" => obj.get_dimensions_or_empty().height.to_value(),
+ "em" => obj.get_dimensions_or_empty().em.to_value(),
+ "ex" => obj.get_dimensions_or_empty().ex.to_value(),
+
+ // the following three are deprecated
+ "title" => None::<String>.to_value(),
+ "desc" => None::<String>.to_value(),
+ "metadata" => None::<String>.to_value(),
+
+ _ => unreachable!("invalid property id={} for RsvgHandle", id),
}
-
- _ => unreachable!("invalid property id {}", id),
}
}
+}
- fn property(&self, _obj: &Self::Type, id: usize, pspec: &ParamSpec) -> glib::Value {
- match pspec.name() {
- "flags" => self.get_flags().to_value(),
- "dpi-x" => self.get_dpi_x().to_value(),
- "dpi-y" => self.get_dpi_y().to_value(),
- "base-uri" => self.get_base_url().to_value(),
- "width" => self.get_dimensions_or_empty().width.to_value(),
- "height" => self.get_dimensions_or_empty().height.to_value(),
- "em" => self.get_dimensions_or_empty().em.to_value(),
- "ex" => self.get_dimensions_or_empty().ex.to_value(),
-
- // the following three are deprecated
- "title" => None::<String>.to_value(),
- "desc" => None::<String>.to_value(),
- "metadata" => None::<String>.to_value(),
-
- _ => unreachable!("invalid property id={} for RsvgHandle", id),
- }
- }
+glib::wrapper! {
+ // We don't use subclass:simple::InstanceStruct and ClassStruct
+ // because we need to maintain the respective _abi_padding of each
+ // of RsvgHandleClass and RsvgHandle.
+ pub struct CHandle(ObjectSubclass<imp::CHandle>);
}
// Keep in sync with tests/src/reference.rs
@@ -616,7 +617,8 @@ impl CairoRectangleExt for cairo::Rectangle {
impl CHandle {
fn set_base_url(&self, url: &str) {
- let state = self.load_state.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let state = imp.load_state.borrow();
match *state {
LoadState::Start => (),
@@ -631,7 +633,7 @@ impl CHandle {
match Url::parse(&url) {
Ok(u) => {
rsvg_log!("setting base_uri to \"{}\"", u.as_str());
- let mut inner = self.inner.borrow_mut();
+ let mut inner = imp.inner.borrow_mut();
inner.base_url.set(u);
}
@@ -650,44 +652,60 @@ impl CHandle {
}
fn get_base_url(&self) -> Option<String> {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
inner.base_url.get().map(|url| url.as_str().to_string())
}
fn get_base_url_as_ptr(&self) -> *const libc::c_char {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
inner.base_url.get_ptr()
}
fn set_dpi_x(&self, dpi_x: f64) {
- let mut inner = self.inner.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+
+ let mut inner = imp.inner.borrow_mut();
let dpi = inner.dpi;
inner.dpi = Dpi::new(dpi_x, dpi.y());
}
fn set_dpi_y(&self, dpi_y: f64) {
- let mut inner = self.inner.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+
+ let mut inner = imp.inner.borrow_mut();
let dpi = inner.dpi;
inner.dpi = Dpi::new(dpi.x(), dpi_y);
}
fn get_dpi_x(&self) -> f64 {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
inner.dpi.x()
}
fn get_dpi_y(&self) -> f64 {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
inner.dpi.y()
}
fn set_flags(&self, flags: HandleFlags) {
- let mut inner = self.inner.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+
+ let mut inner = imp.inner.borrow_mut();
inner.load_flags = LoadFlags::from(flags);
}
fn get_flags(&self) -> HandleFlags {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
HandleFlags::from(inner.load_flags)
}
@@ -697,12 +715,15 @@ impl CHandle {
user_data: glib::ffi::gpointer,
destroy_notify: glib::ffi::GDestroyNotify,
) {
- let mut inner = self.inner.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+
+ let mut inner = imp.inner.borrow_mut();
inner.size_callback = SizeCallback::new(size_func, user_data, destroy_notify);
}
fn write(&self, buf: &[u8]) {
- let mut state = self.load_state.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+ let mut state = imp.load_state.borrow_mut();
match *state {
LoadState::Start => {
@@ -722,8 +743,10 @@ impl CHandle {
}
fn close(&self) -> Result<(), LoadingError> {
- let inner = self.inner.borrow();
- let mut state = self.load_state.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+
+ let inner = imp.inner.borrow();
+ let mut state = imp.load_state.borrow_mut();
match *state {
LoadState::Start => {
@@ -752,8 +775,10 @@ impl CHandle {
stream: &gio::InputStream,
cancellable: Option<&gio::Cancellable>,
) -> Result<(), LoadingError> {
- let state = self.load_state.borrow_mut();
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+
+ let state = imp.load_state.borrow_mut();
+ let inner = imp.inner.borrow();
match *state {
LoadState::Start => {
@@ -784,7 +809,8 @@ impl CHandle {
}
fn get_handle_ref(&self) -> Result<Ref<'_, SvgHandle>, RenderingError> {
- let state = self.load_state.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let state = imp.load_state.borrow();
match *state {
LoadState::Start => {
@@ -813,7 +839,8 @@ impl CHandle {
}
fn make_loader(&self) -> Loader {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let inner = imp.inner.borrow();
Loader::new()
.with_unlimited_size(inner.load_flags.unlimited_size)
@@ -831,7 +858,8 @@ impl CHandle {
}
fn get_dimensions_sub(&self, id: Option<&str>) -> Result<RsvgDimensionData, RenderingError> {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let inner = imp.inner.borrow();
// This function is probably called from the cairo_render functions,
// or is being erroneously called within the size_func.
@@ -874,7 +902,8 @@ impl CHandle {
}
fn get_position_sub(&self, id: Option<&str>) -> Result<RsvgPositionData, RenderingError> {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let inner = imp.inner.borrow();
if id.is_none() {
return Ok(RsvgPositionData { x: 0, y: 0 });
@@ -898,7 +927,8 @@ impl CHandle {
}
fn make_renderer<'a>(&self, handle_ref: &'a Ref<'_, SvgHandle>) -> CairoRenderer<'a> {
- let inner = self.inner.borrow();
+ let imp = imp::CHandle::from_instance(self);
+ let inner = imp.inner.borrow();
let mut renderer = CairoRenderer::new(&*handle_ref).with_dpi(inner.dpi.x(), inner.dpi.y());
@@ -920,7 +950,8 @@ impl CHandle {
}
fn set_stylesheet(&self, css: &str) -> Result<(), LoadingError> {
- match *self.load_state.borrow_mut() {
+ let imp = imp::CHandle::from_instance(self);
+ match *imp.load_state.borrow_mut() {
LoadState::ClosedOk { ref mut handle } => handle.set_stylesheet(css),
_ => {
@@ -1060,7 +1091,8 @@ impl CHandle {
}
fn set_testing(&self, is_testing: bool) {
- let mut inner = self.inner.borrow_mut();
+ let imp = imp::CHandle::from_instance(self);
+ let mut inner = imp.inner.borrow_mut();
inner.is_testing = is_testing;
}
}
@@ -1081,14 +1113,14 @@ fn is_cancellable(obj: *mut gio::ffi::GCancellable) -> bool {
unsafe { instance_of::<gio::Cancellable>(obj as *const _) }
}
-fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a CHandle {
+fn get_rust_handle(handle: *const RsvgHandle) -> CHandle {
let handle = unsafe { &*handle };
- handle.impl_()
+ handle.impl_().instance()
}
#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_get_type() -> glib::ffi::GType {
- CHandle::type_().into_glib()
+ CHandle::static_type().into_glib()
}
#[no_mangle]
@@ -1488,20 +1520,17 @@ pub unsafe extern "C" fn rsvg_handle_get_position_sub(
#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_new() -> *const RsvgHandle {
- let obj: *mut glib::gobject_ffi::GObject =
- glib::Object::new::<CHandle>(&[]).unwrap().to_glib_full();
+ let obj = glib::Object::new::<CHandle>(&[]).unwrap();
- obj as *mut _
+ obj.to_glib_full()
}
#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_new_with_flags(flags: RsvgHandleFlags) -> *const RsvgHandle {
- let obj: *mut glib::gobject_ffi::GObject =
- glib::Object::new::<CHandle>(&[("flags", &HandleFlags::from_bits_truncate(flags))])
- .unwrap()
- .to_glib_full();
+ let obj = glib::Object::new::<CHandle>(&[("flags", &HandleFlags::from_bits_truncate(flags))])
+ .unwrap();
- obj as *mut _
+ obj.to_glib_full()
}
#[no_mangle]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]