[librsvg] Register enums and flags against GType in Rust



commit e6e4da7800e55aa698a35165c41e6578d0b454e4
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Feb 15 09:51:40 2019 -0600

    Register enums and flags against GType in Rust
    
    This is a backport of the relevant code from the "subclass" branch.
    The C code generated by glib-mkenums and its templates did not use
    GOnce, so registration of enums/flags across threads would have been
    buggy.

 Makefile.am                 | 46 ++----------------------
 librsvg/rsvg-handle.c       | 16 +++++++++
 librsvg/rsvg.h              |  7 +++-
 rsvg_internals/src/c_api.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++
 rsvg_internals/src/error.rs |  2 +-
 rsvg_internals/src/lib.rs   |  6 ++++
 6 files changed, 120 insertions(+), 45 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index da9745fe..e4e10ce5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,14 +14,7 @@ headers =                    \
        librsvg/rsvg.h          \
        librsvg/rsvg-cairo.h
 
-enum_sources =                                 \
-       librsvg/librsvg-enum-types.h    \
-       librsvg/librsvg-enum-types.c
-BUILT_SOURCES += $(enum_sources)
-
 librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES =  \
-       librsvg/librsvg-enum-types.c            \
-       librsvg/librsvg-enum-types.h            \
        librsvg/librsvg-features.c              \
        librsvg/librsvg-features.h              \
        librsvg/rsvg-base.c                     \
@@ -41,6 +34,7 @@ RUST_SRC =                                                    \
        rsvg_internals/src/aspect_ratio.rs                      \
        rsvg_internals/src/attributes.rs                        \
        rsvg_internals/src/bbox.rs                              \
+       rsvg_internals/src/c_api.rs                             \
        rsvg_internals/src/clip_path.rs                         \
        rsvg_internals/src/color.rs                             \
        rsvg_internals/src/cond.rs                              \
@@ -207,8 +201,7 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_LIBADD = \
 librsvgincdir = $(includedir)/librsvg-$(RSVG_API_VERSION)/librsvg
 librsvginc_HEADERS =                   \
        $(headers)                      \
-       librsvg/librsvg-features.h      \
-       librsvg/librsvg-enum-types.h
+       librsvg/librsvg-features.h
 
 dist_man_MANS = rsvg-convert.1
 
@@ -285,45 +278,12 @@ EXTRA_DIST =                              \
        tap-driver.sh                   \
        tap-test
 
-CLEANFILES = \
-       $(enum_sources) \
-       librsvg/s-enum-types-h librsvg/s-enum-types-c
-
 ## Put `exec' in the name because this should be installed by
 ## `install-exec', not `install-data'.
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = librsvg-$(RSVG_API_VERSION).pc
 
-librsvg/librsvg-enum-types.h: librsvg/s-enum-types-h
-       @true
-
-librsvg/s-enum-types-h: $(headers) Makefile
-       $(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) \
-                       --fhead "#if !defined (__RSVG_RSVG_H_INSIDE__) && !defined 
(RSVG_COMPILATION)\n#warning \"Including <librsvg/librsvg-enum-types.h> directly is 
deprecated.\"\n#endif\n\n#ifndef __LIBRSVG_ENUM_TYPES_H__\n#define __LIBRSVG_ENUM_TYPES_H__\n\n#include 
<glib-object.h>\n\nG_BEGIN_DECLS\n" \
-                       --fprod "/* enumerations from \"@filename@\" */\n" \
-                       --vhead "GType @enum_name@_get_type (void);\n#define RSVG_TYPE_@ENUMSHORT@ 
(@enum_name@_get_type())\n"  \
-                       --ftail "G_END_DECLS\n\n#endif /* __LIBRSVG_ENUM_TYPES_H__ */" \
-               $(headers) ) > librsvg/tmp-librsvg-enum-types.h \
-       && (cmp -s librsvg/tmp-librsvg-enum-types.h librsvg/librsvg-enum-types.h || cp 
librsvg/tmp-librsvg-enum-types.h librsvg/librsvg-enum-types.h ) \
-       && rm -f librsvg/tmp-librsvg-enum-types.h       \
-       && echo timestamp > $@
-
-librsvg/librsvg-enum-types.c: librsvg/s-enum-types-c librsvg/librsvg-enum-types.h
-       @true
-
-librsvg/s-enum-types-c: $(headers) Makefile
-       $(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) \
-                       --fhead "#include \"librsvg/rsvg.h\"" \
-                       --fprod "\n/* enumerations from \"@filename@\" */" \
-                       --vhead "GType\n@enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if 
(etype == 0) {\n    static const G@Type@Value values[] = {"     \
-                       --vprod "      { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
-                       --vtail "      { 0, NULL, NULL }\n    };\n    etype = g_@type@_register_static 
(\"@EnumName@\", values);\n  }\n  return etype;\n}\n" \
-               $(headers) ) > librsvg/tmp-librsvg-enum-types.c \
-       && (cmp -s librsvg/tmp-librsvg-enum-types.c librsvg/librsvg-enum-types.c || cp 
librsvg/tmp-librsvg-enum-types.c librsvg/librsvg-enum-types.c ) \
-       && rm -f librsvg/tmp-librsvg-enum-types.c \
-       && echo timestamp > $@
-
 DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
 
 if HAVE_INTROSPECTION
@@ -362,7 +322,7 @@ nodist_gir_DATA = $(INTROSPECTION_GIRS)
 typelibsdir = $(libdir)/girepository-1.0
 nodist_typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
 
-CLEANFILES += $(nodist_gir_DATA) $(nodist_typelibs_DATA)
+CLEANFILES = $(nodist_gir_DATA) $(nodist_typelibs_DATA)
 
 if ENABLE_VAPIGEN
 include $(VAPIGEN_MAKEFILE)
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index fa03f6b6..65ae738a 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -338,6 +338,10 @@ extern RsvgHandle *rsvg_handle_rust_new_from_data (const guint8 *data,
                                                    gsize data_len,
                                                    GError **error);
 
+/* Implemented in rsvg_internals/src/c_api.rs */
+extern GType rsvg_rust_error_get_type (void);
+extern GType rsvg_rust_handle_flags_get_type (void);
+
 typedef struct {
     RsvgHandleRust *rust_handle;
 } RsvgHandlePrivate;
@@ -1301,3 +1305,15 @@ rsvg_sax_error_cb (void *data, const char *msg, ...)
 
     g_free (buf);
 }
+
+GType
+rsvg_error_get_type(void)
+{
+    return rsvg_rust_error_get_type();
+}
+
+GType
+rsvg_handle_flags_get_type(void)
+{
+    return rsvg_rust_handle_flags_get_type();
+}
diff --git a/librsvg/rsvg.h b/librsvg/rsvg.h
index cfb694a1..d7a1daca 100644
--- a/librsvg/rsvg.h
+++ b/librsvg/rsvg.h
@@ -70,6 +70,9 @@ typedef enum {
 #define RSVG_ERROR (rsvg_error_quark ())
 GQuark rsvg_error_quark (void) G_GNUC_CONST;
 
+GType rsvg_error_get_type (void);
+#define RSVG_TYPE_ERROR (rsvg_error_get_type())
+
 typedef struct _RsvgHandle RsvgHandle;
 typedef struct _RsvgHandleClass RsvgHandleClass;
 typedef struct _RsvgDimensionData RsvgDimensionData;
@@ -234,6 +237,9 @@ typedef enum /*< flags >*/
     RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA = 1 << 1
 } RsvgHandleFlags;
 
+GType rsvg_handle_flags_get_type (void);
+#define RSVG_TYPE_HANDLE_FLAGS (rsvg_handle_flags_get_type())
+
 RsvgHandle *rsvg_handle_new_with_flags (RsvgHandleFlags flags);
 
 void        rsvg_handle_set_base_gfile (RsvgHandle *handle,
@@ -335,7 +341,6 @@ const char *rsvg_handle_get_metadata    (RsvgHandle *handle);
 
 G_END_DECLS
 
-#include "librsvg-enum-types.h"
 #include "librsvg-features.h"
 #include "rsvg-cairo.h"
 
diff --git a/rsvg_internals/src/c_api.rs b/rsvg_internals/src/c_api.rs
new file mode 100644
index 00000000..83314050
--- /dev/null
+++ b/rsvg_internals/src/c_api.rs
@@ -0,0 +1,88 @@
+use std::sync::Once;
+
+use glib_sys;
+use gobject_sys::{self, GEnumValue, GFlagsValue};
+
+use error::RSVG_ERROR_FAILED;
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_error_get_type() -> glib_sys::GType {
+    static ONCE: Once = Once::new();
+    static mut ETYPE: glib_sys::GType = gobject_sys::G_TYPE_INVALID;
+
+    // We have to store the GEnumValue in a static variable but
+    // that requires it to be Sync. It is not Sync by default
+    // because it contains pointers, so we have define a custom
+    // wrapper type here on which we can implement Sync.
+    #[repr(transparent)]
+    struct GEnumValueWrapper(GEnumValue);
+    unsafe impl Sync for GEnumValueWrapper {}
+
+    static VALUES: [GEnumValueWrapper; 2] = [
+        GEnumValueWrapper(GEnumValue {
+            value: RSVG_ERROR_FAILED,
+            value_name: b"RSVG_ERROR_FAILED\0" as *const u8 as *const _,
+            value_nick: b"failed\0" as *const u8 as *const _,
+        }),
+        GEnumValueWrapper(GEnumValue {
+            value: 0,
+            value_name: 0 as *const _,
+            value_nick: 0 as *const _,
+        }),
+    ];
+
+    ONCE.call_once(|| {
+        ETYPE = gobject_sys::g_enum_register_static(
+            b"RsvgError\0" as *const u8 as *const _,
+            &VALUES as *const GEnumValueWrapper as *const GEnumValue,
+        );
+    });
+
+    ETYPE
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_rust_handle_flags_get_type() -> glib_sys::GType {
+    static ONCE: Once = Once::new();
+    static mut FTYPE: glib_sys::GType = gobject_sys::G_TYPE_INVALID;
+
+    // We have to store the GFlagsValue in a static variable but
+    // that requires it to be Sync. It is not Sync by default
+    // because it contains pointers, so we have define a custom
+    // wrapper type here on which we can implement Sync.
+    #[repr(transparent)]
+    struct GFlagsValueWrapper(GFlagsValue);
+    unsafe impl Sync for GFlagsValueWrapper {}
+
+    static VALUES: [GFlagsValueWrapper; 4] = [
+        GFlagsValueWrapper(GFlagsValue {
+            value: 0, // handle_flags::HandleFlags::NONE.bits(),
+            value_name: b"RSVG_HANDLE_FLAGS_NONE\0" as *const u8 as *const _,
+            value_nick: b"flags-none\0" as *const u8 as *const _,
+        }),
+        GFlagsValueWrapper(GFlagsValue {
+            value: 1 << 0, // HandleFlags::UNLIMITED.to_glib(),
+            value_name: b"RSVG_HANDLE_FLAG_UNLIMITED\0" as *const u8 as *const _,
+            value_nick: b"flag-unlimited\0" as *const u8 as *const _,
+        }),
+        GFlagsValueWrapper(GFlagsValue {
+            value: 1 << 1, // HandleFlags::KEEP_IMAGE_DATA.to_glib(),
+            value_name: b"RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA\0" as *const u8 as *const _,
+            value_nick: b"flag-keep-image-data\0" as *const u8 as *const _,
+        }),
+        GFlagsValueWrapper(GFlagsValue {
+            value: 0,
+            value_name: 0 as *const _,
+            value_nick: 0 as *const _,
+        }),
+    ];
+
+    ONCE.call_once(|| {
+        FTYPE = gobject_sys::g_flags_register_static(
+            b"RsvgHandleFlags\0" as *const u8 as *const _,
+            &VALUES as *const GFlagsValueWrapper as *const GFlagsValue,
+        );
+    });
+
+    FTYPE
+}
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index b763d1d2..a9ef26f5 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -321,7 +321,7 @@ pub fn is_value_error<T>(r: &Result<T, ValueErrorKind>) -> bool {
 pub struct RsvgError;
 
 // Keep in sync with rsvg.h:RsvgError
-const RSVG_ERROR_FAILED: i32 = 0;
+pub const RSVG_ERROR_FAILED: i32 = 0;
 
 impl ErrorDomain for RsvgError {
     fn domain() -> glib::Quark {
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index e979c7ed..2d5d05be 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -35,6 +35,11 @@ extern crate xml as xml_rs;
 #[macro_use]
 extern crate lazy_static;
 
+pub use c_api::{
+    rsvg_rust_error_get_type,
+    rsvg_rust_handle_flags_get_type,
+};
+
 pub use color::{rsvg_css_parse_color, ColorKind, ColorSpec};
 
 pub use dpi::rsvg_rust_set_default_dpi_x_y;
@@ -97,6 +102,7 @@ mod angle;
 mod aspect_ratio;
 mod attributes;
 mod bbox;
+mod c_api;
 mod clip_path;
 mod color;
 mod cond;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]