diff options
author | Federico Mena Quintero <federico@gnome.org> | 2018-02-27 09:44:16 -0600 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2018-02-27 09:44:16 -0600 |
commit | c7f57a38a9b6cf88c6f842f6d16173a6b51b0993 (patch) | |
tree | 40e1c5234e21158331b091b2472f923444334d42 | |
parent | d453061d60720832e42ed80e8d55cf29c78916fd (diff) | |
parent | 3f098e50a32df183fb1b2bd11008577abaeac3e9 (diff) | |
download | librsvg-import-rsvg-rs.tar.gz |
Merge branch 'import-rebased'import-rsvg-rs
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | Makefile.am | 82 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
m--------- | gir | 0 | ||||
-rw-r--r-- | rsvg-rs/.gitignore | 5 | ||||
-rw-r--r-- | rsvg-rs/CHANGELOG.md | 15 | ||||
-rw-r--r-- | rsvg-rs/Cargo.toml | 34 | ||||
-rw-r--r-- | rsvg-rs/Gir.toml | 38 | ||||
-rw-r--r-- | rsvg-rs/Makefile | 32 | ||||
-rw-r--r-- | rsvg-rs/README.md | 17 | ||||
-rw-r--r-- | rsvg-rs/rsvg-sys/Cargo.toml | 30 | ||||
-rw-r--r-- | rsvg-rs/rsvg-sys/Gir.toml | 12 | ||||
-rw-r--r-- | rsvg-rs/rsvg-sys/build.rs | 61 | ||||
-rw-r--r-- | rsvg-rs/rsvg-sys/src/lib.rs | 160 | ||||
-rw-r--r-- | rsvg-rs/src/auto/enums.rs | 6 | ||||
-rw-r--r-- | rsvg-rs/src/auto/flags.rs | 58 | ||||
-rw-r--r-- | rsvg-rs/src/auto/handle.rs | 574 | ||||
-rw-r--r-- | rsvg-rs/src/auto/mod.rs | 14 | ||||
-rw-r--r-- | rsvg-rs/src/dimension_data.rs | 67 | ||||
-rw-r--r-- | rsvg-rs/src/handle.rs | 16 | ||||
-rw-r--r-- | rsvg-rs/src/lib.rs | 125 | ||||
-rw-r--r-- | rsvg-rs/src/position_data.rs | 67 |
22 files changed, 1405 insertions, 19 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..c21670ff --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gir"] + path = gir + url = git@github.com:gtk-rs/gir.git diff --git a/Makefile.am b/Makefile.am index a5a16220..1f6dcc9a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,13 +3,19 @@ SUBDIRS = . gdk-pixbuf-loader tests tools doc win32 NULL = BUILT_SOURCES = +# ---------- Products of the build, to be installed ---------- + +# the main library lib_LTLIBRARIES = librsvg-@RSVG_API_MAJOR_VERSION@.la +# programs bin_PROGRAMS = rsvg-convert if HAVE_GTK_3 bin_PROGRAMS += rsvg-view-3 endif +# ---------- librsvg library ---------- + headers = \ librsvg/rsvg.h \ librsvg/rsvg-cairo.h @@ -123,8 +129,9 @@ cargo_verbose_ = $(cargo_verbose_$(AM_DEFAULT_VERBOSITY)) cargo_verbose_0 = cargo_verbose_1 = --verbose -RUST_LIB=@abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/librsvg_internals.a CARGO_TARGET_DIR=@abs_top_builddir@/target +RUST_BINARIES_DIR=$(CARGO_TARGET_DIR)/@RUST_TARGET_SUBDIR@ +RUST_LIB=$(RUST_BINARIES_DIR)/librsvg_internals.a check-local: cd $(srcdir) && \ @@ -298,10 +305,11 @@ librsvg/s-enum-types-c: $(headers) Makefile DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc -if HAVE_INTROSPECTION +# ---------- GObject Introspection ---------- + -include $(INTROSPECTION_MAKEFILE) -INTROSPECTION_GIRS = Rsvg-@RSVG_API_VERSION@.gir +INTROSPECTION_GIR = Rsvg-@RSVG_API_VERSION@.gir INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --symbol-prefix=rsvg --symbol-prefix=librsvg INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) @@ -329,13 +337,15 @@ Rsvg_@RSVG_API_VERSION_U@_gir_LIBS = librsvg-@RSVG_API_MAJOR_VERSION@.la Rsvg_@RSVG_API_VERSION_U@_gir_SCANNERFLAGS = --c-include="librsvg/rsvg.h" girdir = $(datadir)/gir-1.0 -nodist_gir_DATA = $(INTROSPECTION_GIRS) +nodist_gir_DATA = $(INTROSPECTION_GIR) typelibsdir = $(libdir)/girepository-1.0 -nodist_typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +nodist_typelibs_DATA = $(INTROSPECTION_GIR:.gir=.typelib) CLEANFILES += $(nodist_gir_DATA) $(nodist_typelibs_DATA) +# ---------- Vala binding ---------- + if ENABLE_VAPIGEN include $(VAPIGEN_MAKEFILE) @@ -354,8 +364,6 @@ CLEANFILES += $(VAPIGEN_VAPIS) endif # ENABLE_VAPIGEN -endif # HAVE_INTROSPECTION - # ------------------- MSVC Build Items ---------------- MSVCPROJS = rsvg rsvg-convert @@ -377,9 +385,7 @@ MSVCPROJ_GENERATED = \ $(top_builddir)/win32/vs12/rsvg.vcxproj \ $(top_builddir)/win32/vs12/rsvg-convert.vcxproj -if HAVE_INTROSPECTION - -MSVC_INTROSPECT_GIRS = $(INTROSPECTION_GIRS) +MSVC_INTROSPECT_GIRS = $(INTROSPECTION_GIR) INTROSPECTION_INTERMEDIATE_ITEMS = \ $(top_builddir)/win32/Rsvg-@RSVG_API_VERSION@.gir.msvc.introspect \ @@ -396,13 +402,65 @@ Rsvg_@RSVG_API_VERSION_U@_gir_MSVC_SCANNERFLAGS = $(Rsvg_@RSVG_API_VERSION_U@_gi MSVCPROJ_GENERATED += $(INTROSPECTION_INTERMEDIATE_ITEMS) include $(top_srcdir)/win32/Makefile.msvc-introspection -endif # HAVE_INTROSPECTION $(MSVCPROJ_GENERATED): $(top_builddir)/win32/vs12/rsvg.vs12.headers EXTRA_DIST += $(MSVCPROJ_GENERATED) -# ChangeLog generation +# ---------- gir tool from gtk-rs ---------- + +GIR_SRC= \ + gir/LICENSE \ + gir/build.rs \ + gir/Cargo.toml \ + gir/Gir_Gio.toml \ + gir/README.md \ + gir/Gir_Gtk.toml \ + gir/Cargo.lock \ + $(shell find gir/src -name '*.rs') +# do we need to run find(1) in gir/tests as well? + +EXTRA_DIST += $(GIR_SRC) + +GIR = $(RUST_BINARIES_DIR)/gir + +# $(GIR_SRC): +# git submodule update --init + +$(GIR): $(GIR_SRC) + +cd $(top_srcdir)/gir && \ + PKG_CONFIG_ALLOW_CROSS=1 \ + PKG_CONFIG='$(PKG_CONFIG)' \ + CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \ + cargo build $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS) + +# ---------- rsvg-rs binding ---------- + +RS_BINDING_LIB=$(RUST_BINARIES_DIR)/librsvg_rs.rlib + +RS_BINDING_GIR=rsvg-rs/$(INTROSPECTION_GIR) + +# Copy the generated .gir into rsvg-rs so it can be used as a standalone crate +$(RS_BINDING_GIR): $(INTROSPECTION_GIR) + cp $(INTROSPECTION_GIR) $(RS_BINDING_GIR) + +RS_BINDING_SOURCES= \ + rsvg-rs/Cargo.toml \ + rsvg-rs/Gir.toml \ + rsvg-rs/src/dimension_data.rs \ + rsvg-rs/src/handle.rs \ + rsvg-rs/src/lib.rs \ + rsvg-rs/src/position_data.rs + +# Build the binding +$(RS_BINDING_LIB): $(RS_BINDING_GIR) $(RS_BINDING_SOURCES) $(GIR) + +cd $(top_srcdir)/rsvg-rs && \ + PKG_CONFIG_ALLOW_CROSS=1 \ + PKG_CONFIG='$(PKG_CONFIG)' \ + CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \ + cargo build $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS) + +# ---------- ChangeLog generation ---------- ChangeLog: $(AM_V_GEN) if test -d $(top_srcdir)/.git; then \ diff --git a/configure.ac b/configure.ac index 9f8dce29..40a06a6f 100644 --- a/configure.ac +++ b/configure.ac @@ -289,12 +289,7 @@ AC_SUBST([RUST_TARGET_SUBDIR]) dnl =========================================================================== dnl Build introspectable bindings -# No automagic please! -if test -z "$enable_introspection"; then - enable_introspection=yes -fi - -GOBJECT_INTROSPECTION_CHECK([0.10.8]) +GOBJECT_INTROSPECTION_REQUIRE([0.10.8]) # Vala bindings VAPIGEN_CHECK([0.17.1.26],,,[no]) @@ -378,7 +373,6 @@ librsvg-$VERSION Debugging information for Rust: ${debug_release} - Build introspectable bindings: ${found_introspection} Build Vala bindings: ${enable_vala} Build GdkPixbuf loader: ${enable_pixbuf_loader} GTK+ $GTK3_REQUIRED or later: ${have_gtk_3} diff --git a/gir b/gir new file mode 160000 +Subproject 6114d1c7e248c982fb67c73fbf1b4318675a88e diff --git a/rsvg-rs/.gitignore b/rsvg-rs/.gitignore new file mode 100644 index 00000000..5141448e --- /dev/null +++ b/rsvg-rs/.gitignore @@ -0,0 +1,5 @@ +.idea +target/ +**/*.rs.bk +Cargo.lock +vendor.md
\ No newline at end of file diff --git a/rsvg-rs/CHANGELOG.md b/rsvg-rs/CHANGELOG.md new file mode 100644 index 00000000..bcc0e694 --- /dev/null +++ b/rsvg-rs/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +### 0.3.0 + +- Works with `gtk = "0.3.0"` + +### 0.2.0 + +- Works with `gtk = "0.2.0"` +- Regenerated API (`HandleExt` trait introduced) + +### 0.1.3 + +- Initial commit +- Works with `gtk = "0.1.3"` diff --git a/rsvg-rs/Cargo.toml b/rsvg-rs/Cargo.toml new file mode 100644 index 00000000..24cf5d96 --- /dev/null +++ b/rsvg-rs/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "rsvg" +version = "0.3.0" +authors = ["selaux"] +description = "Rust bindings for the Rsvg library" +repository = "https://github.com/selaux/rsvg-rs" +license = "MIT" + +keywords = ["rsvg", "svg", "gtk-rs"] +include = ["src/**/*", "Cargo.toml"] + +[lib] +name = "rsvg" + +[dependencies] +libc = "0.2" +bitflags = "0.9" +glib = "0.4.0" +glib-sys = "0.5.0" +gobject-sys = "0.5.0" +gdk-pixbuf = "0.3.0" + +[dev-dependencies] +# image = "0.13.0" +# imageproc = "0.8.0" +gtk = "0.3.0" + +[dependencies.cairo-rs] +version = "0.3.0" +features = ["png"] + +[dependencies.rsvg-sys] +version = "0.5.0" +path = "./rsvg-sys" diff --git a/rsvg-rs/Gir.toml b/rsvg-rs/Gir.toml new file mode 100644 index 00000000..d71fafa2 --- /dev/null +++ b/rsvg-rs/Gir.toml @@ -0,0 +1,38 @@ +[options] +girs_dir = "gir-files" +library = "Rsvg" +version = "2.0" +min_cfg_version = "2.36" +target_path = "." +work_mode = "normal" +generate_safety_asserts = false +deprecate_by_min_version = true + +generate = [ + "Rsvg.HandleFlags" +] + +manual = [ + "Rsvg.DimensionData", + "Rsvg.PositionData", + "cairo.Context", + "GdkPixbuf.Pixbuf", + "GLib.Error" +] + +[[object]] +name = "Rsvg.Handle" +status = "generate" + [[object.function]] + pattern = "render_cairo(_sub)?" + [[object.function.parameter]] + name = "cr" + const = true + + [[object.function]] + name = "get_base_uri" + ignore = true + + [[object.property]] + name = "base-uri" + ignore = true
\ No newline at end of file diff --git a/rsvg-rs/Makefile b/rsvg-rs/Makefile new file mode 100644 index 00000000..56558613 --- /dev/null +++ b/rsvg-rs/Makefile @@ -0,0 +1,32 @@ +RUSTDOC_STRIPPER = target/rustdoc-stripper/bin/rustdoc-stripper +GIR = target/gir/bin/gir +GIR_FILES = $(shell pkg-config --variable girdir gobject-introspection-1.0) +SYS_FILES = rsvg-sys/src/lib.rs +DOCS = vendor.md + +src/auto/mod.rs : Gir.toml $(GIR) $(RUSTDOC_STRIPPER) $(GIR_FILES) $(SYS_FILES) $(DOCS) + $(GIR) -c Gir.toml -d $(GIR_FILES) + $(RUSTDOC_STRIPPER) -g -o $(DOCS) -d src/auto + +$(DOCS): Gir.toml $(GIR) $(GIR_FILES) + $(GIR) -c $< -d $(GIR_FILES) -m doc + +.PHONY: clean +clean: + rm -rf src/auto $(SYS_FILES) $(DOCS) + +$(SYS_FILES): rsvg-sys/Gir.toml $(GIR) $(GIR_FILES) + $(GIR) -c $< -o $(abspath rsvg-sys) -d $(GIR_FILES) + +$(RUSTDOC_STRIPPER) : + cargo install --root target/rustdoc-stripper rustdoc-stripper --version "0.1.5" + +$(GIR) : + cargo install --root target/gir --git https://github.com/gtk-rs/gir --rev d50d839ceaed9cc5eabac729dbc161c295306270 gir + +.PHONY: gir +gir : src/auto/mod.rs + +.PHONY: gir-sys +gir-sys : $(SYS_FILES) + diff --git a/rsvg-rs/README.md b/rsvg-rs/README.md new file mode 100644 index 00000000..ae9f76e4 --- /dev/null +++ b/rsvg-rs/README.md @@ -0,0 +1,17 @@ +# rsvg-rs + +[](https://crates.io/crates/rsvg) +[](https://docs.rs/crate/rsvg) +[](https://travis-ci.org/selaux/rsvg-rs) + +[libRSVG](https://wiki.gnome.org/action/show/Projects/LibRsvg?action=show&redirect=LibRsvg) bindings for Rust. + +Based on [Gtk-rs project](http://gtk-rs.org/) bindings. + +## Example + +See [examples folder](/examples) + +## License + +MIT diff --git a/rsvg-rs/rsvg-sys/Cargo.toml b/rsvg-rs/rsvg-sys/Cargo.toml new file mode 100644 index 00000000..b0d01985 --- /dev/null +++ b/rsvg-rs/rsvg-sys/Cargo.toml @@ -0,0 +1,30 @@ +[build-dependencies] +pkg-config = "0.3.7" + +[dependencies] +atk-sys = "0.5.0" +bitflags = "1.0" +cairo-sys-rs = "0.5.0" +gdk-pixbuf-sys = "0.5.0" +gdk-sys = "0.5.0" +gio-sys = "0.5.0" +glib-sys = "0.5.0" +gobject-sys = "0.5.0" +libc = "0.2" +pango-sys = "0.5.0" + +[features] +dox = [] + +[lib] +name = "rsvg_sys" + +[package] +authors = ["selaux"] +build = "build.rs" +description = "Rust bindings for the Rsvg library (ffi)" +license = "MIT" +links = "rsvg" +name = "rsvg-sys" +repository = "https://github.com/selaux/rsvg-rs" +version = "0.5.0" diff --git a/rsvg-rs/rsvg-sys/Gir.toml b/rsvg-rs/rsvg-sys/Gir.toml new file mode 100644 index 00000000..980c87a8 --- /dev/null +++ b/rsvg-rs/rsvg-sys/Gir.toml @@ -0,0 +1,12 @@ +[options] +work_mode = "sys" +library = "Rsvg" +version = "2.0" +min_cfg_version = "2.36" +external_libraries = [ + "GLib", + "GObject", + "Gio", + "GdkPixbuf", + "Cairo", +] diff --git a/rsvg-rs/rsvg-sys/build.rs b/rsvg-rs/rsvg-sys/build.rs new file mode 100644 index 00000000..405c80f8 --- /dev/null +++ b/rsvg-rs/rsvg-sys/build.rs @@ -0,0 +1,61 @@ +extern crate pkg_config; + +use pkg_config::{Config, Error}; +use std::env; +use std::io::prelude::*; +use std::io; +use std::process; + +fn main() { + if let Err(s) = find() { + let _ = writeln!(io::stderr(), "{}", s); + process::exit(1); + } +} + +fn find() -> Result<(), Error> { + let package_name = "librsvg-2.0"; + let shared_libs = ["rsvg-2"]; + let version = { + "2.36" + }; + + if let Ok(lib_dir) = env::var("GTK_LIB_DIR") { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + println!("cargo:rustc-link-search=native={}", lib_dir); + return Ok(()) + } + + let target = env::var("TARGET").expect("TARGET environment variable doesn't exist"); + let hardcode_shared_libs = target.contains("windows"); + + let mut config = Config::new(); + config.atleast_version(version); + if hardcode_shared_libs { + config.cargo_metadata(false); + } + match config.probe(package_name) { + Ok(library) => { + if hardcode_shared_libs { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + for path in library.link_paths.iter() { + println!("cargo:rustc-link-search=native={}", + path.to_str().expect("library path doesn't exist")); + } + } + Ok(()) + } + Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + Ok(()) + } + Err(err) => Err(err), + } +} + diff --git a/rsvg-rs/rsvg-sys/src/lib.rs b/rsvg-rs/rsvg-sys/src/lib.rs new file mode 100644 index 00000000..7fe0ea91 --- /dev/null +++ b/rsvg-rs/rsvg-sys/src/lib.rs @@ -0,0 +1,160 @@ +// This file was generated by gir (d50d839) from gir-files (???) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals)] + +extern crate libc; +#[macro_use] extern crate bitflags; +extern crate glib_sys as glib; +extern crate gobject_sys as gobject; +extern crate gio_sys as gio; +extern crate gdk_pixbuf_sys as gdk_pixbuf; +extern crate cairo_sys as cairo; + +#[allow(unused_imports)] +use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double, + c_short, c_ushort, c_long, c_ulong, + c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType, Volatile}; + +// Enums +pub type Error = c_int; +pub const RSVG_ERROR_FAILED: Error = 0; +pub type RsvgError = Error; + +// Constants +pub const LIBRSVG_MAJOR_VERSION: c_int = 2; +pub const LIBRSVG_MICRO_VERSION: c_int = 2; +pub const LIBRSVG_MINOR_VERSION: c_int = 42; +pub const LIBRSVG_VERSION: *const c_char = b"2.42.2\0" as *const u8 as *const c_char; + +// Flags +bitflags! { + #[repr(C)] + pub struct RsvgHandleFlags: c_uint { + const FLAGS_NONE = 0; + const FLAG_UNLIMITED = 1; + const FLAG_KEEP_IMAGE_DATA = 2; + } +} +pub const RSVG_HANDLE_FLAGS_NONE: RsvgHandleFlags = RsvgHandleFlags::FLAGS_NONE; +pub const RSVG_HANDLE_FLAG_UNLIMITED: RsvgHandleFlags = RsvgHandleFlags::FLAG_UNLIMITED; +pub const RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA: RsvgHandleFlags = RsvgHandleFlags::FLAG_KEEP_IMAGE_DATA; + +// Records +#[repr(C)] +pub struct RsvgDimensionData { + pub width: c_int, + pub height: c_int, + pub em: c_double, + pub ex: c_double, +} + +impl ::std::fmt::Debug for RsvgDimensionData { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "RsvgDimensionData @ {:?}", self as *const _) + } +} + +#[repr(C)] +pub struct RsvgHandleClass { + pub parent: gobject::GObjectClass, + pub _abi_padding: [gpointer; 15], +} + +impl ::std::fmt::Debug for RsvgHandleClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "RsvgHandleClass @ {:?}", self as *const _) + } +} + +#[repr(C)] +pub struct RsvgHandlePrivate(c_void); + +impl ::std::fmt::Debug for RsvgHandlePrivate { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "RsvgHandlePrivate @ {:?}", self as *const _) + } +} + +#[repr(C)] +pub struct RsvgPositionData { + pub x: c_int, + pub y: c_int, +} + +impl ::std::fmt::Debug for RsvgPositionData { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "RsvgPositionData @ {:?}", self as *const _) + } +} + +// Classes +#[repr(C)] +pub struct RsvgHandle { + pub parent: gobject::GObject, + pub priv_: *mut RsvgHandlePrivate, + pub _abi_padding: [gpointer; 15], +} + +impl ::std::fmt::Debug for RsvgHandle { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("RsvgHandle @ {:?}", self as *const _)) + .field("parent", &self.parent) + .field("priv_", &self.priv_) + .field("_abi_padding", &self._abi_padding) + .finish() + } +} + +extern "C" { + + //========================================================================= + // RsvgError + //========================================================================= + pub fn rsvg_error_get_type() -> GType; + pub fn rsvg_error_quark() -> glib::GQuark; + + //========================================================================= + // RsvgHandleFlags + //========================================================================= + pub fn rsvg_handle_flags_get_type() -> GType; + + //========================================================================= + // RsvgHandle + //========================================================================= + pub fn rsvg_handle_get_type() -> GType; + pub fn rsvg_handle_new() -> *mut RsvgHandle; + pub fn rsvg_handle_new_from_data(data: *mut u8, data_len: size_t, error: *mut *mut glib::GError) -> *mut RsvgHandle; + pub fn rsvg_handle_new_from_file(file_name: *const c_char, error: *mut *mut glib::GError) -> *mut RsvgHandle; + pub fn rsvg_handle_new_from_gfile_sync(file: *mut gio::GFile, flags: RsvgHandleFlags, cancellable: *mut gio::GCancellable, error: *mut *mut glib::GError) -> *mut RsvgHandle; + pub fn rsvg_handle_new_from_stream_sync(input_stream: *mut gio::GInputStream, base_file: *mut gio::GFile, flags: RsvgHandleFlags, cancellable: *mut gio::GCancellable, error: *mut *mut glib::GError) -> *mut RsvgHandle; + pub fn rsvg_handle_new_with_flags(flags: RsvgHandleFlags) -> *mut RsvgHandle; + pub fn rsvg_handle_close(handle: *mut RsvgHandle, error: *mut *mut glib::GError) -> gboolean; + pub fn rsvg_handle_get_base_uri(handle: *mut RsvgHandle) -> *const c_char; + pub fn rsvg_handle_get_dimensions(handle: *mut RsvgHandle, dimension_data: *mut RsvgDimensionData); + pub fn rsvg_handle_get_dimensions_sub(handle: *mut RsvgHandle, dimension_data: *mut RsvgDimensionData, id: *const c_char) -> gboolean; + pub fn rsvg_handle_get_pixbuf(handle: *mut RsvgHandle) -> *mut gdk_pixbuf::GdkPixbuf; + pub fn rsvg_handle_get_pixbuf_sub(handle: *mut RsvgHandle, id: *const c_char) -> *mut gdk_pixbuf::GdkPixbuf; + pub fn rsvg_handle_get_position_sub(handle: *mut RsvgHandle, position_data: *mut RsvgPositionData, id: *const c_char) -> gboolean; + pub fn rsvg_handle_has_sub(handle: *mut RsvgHandle, id: *const c_char) -> gboolean; + pub fn rsvg_handle_internal_set_testing(handle: *mut RsvgHandle, testing: gboolean); + pub fn rsvg_handle_read_stream_sync(handle: *mut RsvgHandle, stream: *mut gio::GInputStream, cancellable: *mut gio::GCancellable, error: *mut *mut glib::GError) -> gboolean; + pub fn rsvg_handle_render_cairo(handle: *mut RsvgHandle, cr: *mut cairo::cairo_t) -> gboolean; + pub fn rsvg_handle_render_cairo_sub(handle: *mut RsvgHandle, cr: *mut cairo::cairo_t, id: *const c_char) -> gboolean; + pub fn rsvg_handle_set_base_gfile(handle: *mut RsvgHandle, base_file: *mut gio::GFile); + pub fn rsvg_handle_set_base_uri(handle: *mut RsvgHandle, base_uri: *const c_char); + pub fn rsvg_handle_set_dpi(handle: *mut RsvgHandle, dpi: c_double); + pub fn rsvg_handle_set_dpi_x_y(handle: *mut RsvgHandle, dpi_x: c_double, dpi_y: c_double); + pub fn rsvg_handle_write(handle: *mut RsvgHandle, buf: *mut u8, count: size_t, error: *mut *mut glib::GError) -> gboolean; + + //========================================================================= + // Other functions + //========================================================================= + pub fn rsvg_cleanup(); + pub fn rsvg_set_default_dpi(dpi: c_double); + pub fn rsvg_set_default_dpi_x_y(dpi_x: c_double, dpi_y: c_double); + +} diff --git a/rsvg-rs/src/auto/enums.rs b/rsvg-rs/src/auto/enums.rs new file mode 100644 index 00000000..956a81a1 --- /dev/null +++ b/rsvg-rs/src/auto/enums.rs @@ -0,0 +1,6 @@ +// This file was generated by gir (d50d839) from gir-files (???) +// DO NOT EDIT + +use ffi; +use glib::translate::*; + diff --git a/rsvg-rs/src/auto/flags.rs b/rsvg-rs/src/auto/flags.rs new file mode 100644 index 00000000..b53bd76b --- /dev/null +++ b/rsvg-rs/src/auto/flags.rs @@ -0,0 +1,58 @@ +// This file was generated by gir (d50d839) from gir-files (???) +// DO NOT EDIT + +use ffi; +use glib::Type; +use glib::StaticType; +use glib::value::{Value, SetValue, FromValue, FromValueOptional}; +use gobject_ffi; +use glib::translate::*; + +bitflags! { + pub struct HandleFlags: u32 { + const FLAGS_NONE = 0; + const FLAG_UNLIMITED = 1; + const FLAG_KEEP_IMAGE_DATA = 2; + } +} + +#[doc(hidden)] +impl ToGlib for HandleFlags { + type GlibType = ffi::RsvgHandleFlags; + + fn to_glib(&self) -> ffi::RsvgHandleFlags { + ffi::RsvgHandleFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib<ffi::RsvgHandleFlags> for HandleFlags { + fn from_glib(value: ffi::RsvgHandleFlags) -> HandleFlags { + HandleFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for HandleFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::rsvg_handle_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for HandleFlags { + unsafe fn from_value_optional(value: &Value) -> Option<Self> { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for HandleFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::RsvgHandleFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for HandleFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + diff --git a/rsvg-rs/src/auto/handle.rs b/rsvg-rs/src/auto/handle.rs new file mode 100644 index 00000000..9f7a342c --- /dev/null +++ b/rsvg-rs/src/auto/handle.rs @@ -0,0 +1,574 @@ +// This file was generated by gir (d50d839) from gir-files (???) +// DO NOT EDIT + +use DimensionData; +use Error; +use HandleFlags; +use PositionData; +use cairo; +use ffi; +use gdk_pixbuf; +use glib; +use glib::StaticType; +use glib::Value; +use glib::object::Downcast; +use glib::object::IsA; +use glib::signal::SignalHandlerId; +use glib::signal::connect; +use glib::translate::*; +use glib_ffi; +use gobject_ffi; +use std::boxed::Box as Box_; +use std::mem; +use std::mem::transmute; +use std::ptr; + +glib_wrapper! { + pub struct Handle(Object<ffi::RsvgHandle, ffi::RsvgHandleClass>); + + match fn { + get_type => || ffi::rsvg_handle_get_type(), + } +} + +impl Handle { + /// Returns a new rsvg handle. Must be freed with `gobject::Object::unref`. This + /// handle can be used for dynamically loading an image. You need to feed it + /// data using `HandleExt::write`, then call `HandleExt::close` when done. + /// Afterwords, you can render it using Cairo or get a `gdk_pixbuf::Pixbuf` from it. When + /// finished, free with `gobject::Object::unref`. No more than one image can be loaded + /// with one handle. + /// + /// # Returns + /// + /// A new `Handle` + pub fn new() -> Handle { + unsafe { + from_glib_full(ffi::rsvg_handle_new()) + } + } + + /// Loads the SVG specified by `data`. + /// ## `data` + /// The SVG data + /// ## `data_len` + /// The length of `data`, in bytes + /// + /// # Returns + /// + /// A `Handle` or `None` if an error occurs. + pub fn new_from_data(data: &[u8]) -> Result<Handle, Error> { + let data_len = data.len() as usize; + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::rsvg_handle_new_from_data(data.to_glib_none().0, data_len, &mut error); + if error.is_null() { Ok(from_glib_full(ret)) } else { Err(from_glib_full(error)) } + } + } + + /// Loads the SVG specified by `file_name`. + /// ## `file_name` + /// The file name to load. If built with gnome-vfs, can be a URI. + /// + /// # Returns + /// + /// A `Handle` or `None` if an error occurs. + pub fn new_from_file(file_name: &str) -> Result<Handle, Error> { + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::rsvg_handle_new_from_file(file_name.to_glib_none().0, &mut error); + if error.is_null() { Ok(from_glib_full(ret)) } else { Err(from_glib_full(error)) } + } + } + + //pub fn new_from_gfile_sync<'a, P: IsA</*Ignored*/gio::File>, Q: Into<Option<&'a /*Ignored*/gio::Cancellable>>>(file: &P, flags: HandleFlags, cancellable: Q) -> Result<Handle, Error> { + // unsafe { TODO: call ffi::rsvg_handle_new_from_gfile_sync() } + //} + + //pub fn new_from_stream_sync<'a, 'b, P: IsA</*Ignored*/gio::InputStream>, Q: IsA</*Ignored*/gio::File> + 'a, R: Into<Option<&'a Q>>, S: Into<Option<&'b /*Ignored*/gio::Cancellable>>>(input_stream: &P, base_file: R, flags: HandleFlags, cancellable: S) -> Result<Handle, Error> { + // unsafe { TODO: call ffi::rsvg_handle_new_from_stream_sync() } + //} + + /// Creates a new `Handle` with flags `flags`. + /// ## `flags` + /// flags from `HandleFlags` + /// + /// # Returns + /// + /// a new `Handle` + pub fn new_with_flags(flags: HandleFlags) -> Handle { + unsafe { + from_glib_full(ffi::rsvg_handle_new_with_flags(flags.to_glib())) + } + } +} + +impl Default for Handle { + fn default() -> Self { + Self::new() + } +} + +/// Trait containing all `Handle` methods. +/// +/// # Implementors +/// +/// [`Handle`](struct.Handle.html) +pub trait HandleExt { + /// Closes `self`, to indicate that loading the image is complete. This will + /// return `true` if the loader closed successfully. Note that `self` isn't + /// freed until `gobject::Object::unref` is called. + /// + /// # Returns + /// + /// `true` on success, or `false` on error + fn close(&self) -> Result<(), Error>; + + /// Get the SVG's size. Do not call from within the size_func callback, because an infinite loop will occur. + /// ## `dimension_data` + /// A place to store the SVG's size + fn get_dimensions(&self) -> DimensionData; + + /// Get the size of a subelement of the SVG file. Do not call from within the + /// size_func callback, because an infinite loop will occur. + /// ## `dimension_data` + /// A place to store the SVG's size + /// ## `id` + /// An element's id within the SVG, starting with "##", for + /// example, "#`layer1`"; or `None` to use the whole SVG. + fn get_dimensions_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<DimensionData>; + + /// Returns the pixbuf loaded by `self`. The pixbuf returned will be reffed, so + /// the caller of this function must assume that ref. If insufficient data has + /// been read to create the pixbuf, or an error occurred in loading, then `None` + /// will be returned. Note that the pixbuf may not be complete until + /// `HandleExt::close` has been called. + /// + /// # Returns + /// + /// the pixbuf loaded by `self`, or `None`. + fn get_pixbuf(&self) -> Option<gdk_pixbuf::Pixbuf>; + + /// Returns the pixbuf loaded by `self`. The pixbuf returned will be reffed, so + /// the caller of this function must assume that ref. If insufficient data has + /// been read to create the pixbuf, or an error occurred in loading, then `None` + /// will be returned. Note that the pixbuf may not be complete until + /// `HandleExt::close` has been called. + /// ## `id` + /// An element's id within the SVG, starting with "##", for + /// example, "#`layer1`"; or `None` to use the whole SVG. + /// + /// # Returns + /// + /// the pixbuf loaded by `self`, or `None`. + fn get_pixbuf_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<gdk_pixbuf::Pixbuf>; + + /// Get the position of a subelement of the SVG file. Do not call from within + /// the size_func callback, because an infinite loop will occur. + /// ## `position_data` + /// A place to store the SVG fragment's position. + /// ## `id` + /// An element's id within the SVG, starting with "##", for + /// example, "#`layer1`"; or `None` to use the whole SVG. + fn get_position_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<PositionData>; + + /// Checks whether the element `id` exists in the SVG document. + /// ## `id` + /// an element's id within the SVG, starting with "##", for example, "#`layer1`". + /// + /// # Returns + /// + /// `true` if `id` exists in the SVG document + fn has_sub(&self, id: &str) -> bool; + + fn internal_set_testing(&self, testing: bool); + + //fn read_stream_sync<'a, P: IsA</*Ignored*/gio::InputStream>, Q: Into<Option<&'a /*Ignored*/gio::Cancellable>>>(&self, stream: &P, cancellable: Q) -> Result<(), Error>; + + /// Draws a SVG to a Cairo surface + /// ## `cr` + /// A Cairo renderer + /// + /// # Returns + /// + /// `true` if drawing succeeded. + fn render_cairo(&self, cr: &cairo::Context) -> bool; + + /// Draws a subset of a SVG to a Cairo surface + /// ## `cr` + /// A Cairo renderer + /// ## `id` + /// An element's id within the SVG, or `None` to render + /// the whole SVG. For example, if you have a layer called "layer1" + /// that you wish to render, pass "#`layer1`" as the id. + /// + /// # Returns + /// + /// `true` if drawing succeeded. + fn render_cairo_sub<'a, P: Into<Option<&'a str>>>(&self, cr: &cairo::Context, id: P) -> bool; + + //fn set_base_gfile<P: IsA</*Ignored*/gio::File>>(&self, base_file: &P); + + /// Set the base URI for this SVG. This can only be called before `HandleExt::write` + /// has been called. + /// ## `base_uri` + /// The base uri + fn set_base_uri(&self, base_uri: &str); + + /// Sets the DPI for the outgoing pixbuf. Common values are + /// 75, 90, and 300 DPI. Passing a number <= 0 to `dpi` will + /// reset the DPI to whatever the default value happens to be. + /// ## `dpi` + /// Dots Per Inch (aka Pixels Per Inch) + fn set_dpi(&self, dpi: f64); + + /// Sets the DPI for the outgoing pixbuf. Common values are + /// 75, 90, and 300 DPI. Passing a number <= 0 to `dpi_x` or `dpi_y` will + /// reset the DPI to whatever the default value happens to be. + /// ## `dpi_x` + /// Dots Per Inch (aka Pixels Per Inch) + /// ## `dpi_y` + /// Dots Per Inch (aka Pixels Per Inch) + fn set_dpi_x_y(&self, dpi_x: f64, dpi_y: f64); + + /// Loads the next `count` bytes of the image. This will return `true` if the data + /// was loaded successful, and `false` if an error occurred. In the latter case, + /// the loader will be closed, and will not accept further writes. If `false` is + /// returned, `error` will be set to an error from the `Error` domain. Errors + /// from `gio::IOErrorEnum` are also possible. + /// ## `buf` + /// pointer to svg data + /// ## `count` + /// length of the `buf` buffer in bytes + /// + /// # Returns + /// + /// `true` on success, or `false` on error + fn write(&self, buf: &[u8]) -> Result<(), Error>; + + fn get_property_dpi_x(&self) -> f64; + + fn set_property_dpi_x(&self, dpi_x: f64); + + fn get_property_dpi_y(&self) -> f64; + + fn set_property_dpi_y(&self, dpi_y: f64); + + fn get_property_em(&self) -> f64; + + fn get_property_ex(&self) -> f64; + + /// Flags from `HandleFlags`. + fn get_property_flags(&self) -> HandleFlags; + + fn get_property_height(&self) -> i32; + + fn get_property_width(&self) -> i32; + + fn connect_property_dpi_x_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_dpi_y_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_em_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_ex_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_flags_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_height_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; + + fn connect_property_width_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId; +} + +impl<O: IsA<Handle> + IsA<glib::object::Object>> HandleExt for O { + fn close(&self) -> Result<(), Error> { + unsafe { + let mut error = ptr::null_mut(); + let _ = ffi::rsvg_handle_close(self.to_glib_none().0, &mut error); + if error.is_null() { Ok(()) } else { Err(from_glib_full(error)) } + } + } + + fn get_dimensions(&self) -> DimensionData { + unsafe { + let mut dimension_data = DimensionData::uninitialized(); + ffi::rsvg_handle_get_dimensions(self.to_glib_none().0, dimension_data.to_glib_none_mut().0); + dimension_data + } + } + + fn get_dimensions_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<DimensionData> { + let id = id.into(); + let id = id.to_glib_none(); + unsafe { + let mut dimension_data = DimensionData::uninitialized(); + let ret = from_glib(ffi::rsvg_handle_get_dimensions_sub(self.to_glib_none().0, dimension_data.to_glib_none_mut().0, id.0)); + if ret { Some(dimension_data) } else { None } + } + } + + fn get_pixbuf(&self) -> Option<gdk_pixbuf::Pixbuf> { + unsafe { + from_glib_full(ffi::rsvg_handle_get_pixbuf(self.to_glib_none().0)) + } + } + + fn get_pixbuf_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<gdk_pixbuf::Pixbuf> { + let id = id.into(); + let id = id.to_glib_none(); + unsafe { + from_glib_full(ffi::rsvg_handle_get_pixbuf_sub(self.to_glib_none().0, id.0)) + } + } + + fn get_position_sub<'a, P: Into<Option<&'a str>>>(&self, id: P) -> Option<PositionData> { + let id = id.into(); + let id = id.to_glib_none(); + unsafe { + let mut position_data = PositionData::uninitialized(); + let ret = from_glib(ffi::rsvg_handle_get_position_sub(self.to_glib_none().0, position_data.to_glib_none_mut().0, id.0)); + if ret { Some(position_data) } else { None } + } + } + + fn has_sub(&self, id: &str) -> bool { + unsafe { + from_glib(ffi::rsvg_handle_has_sub(self.to_glib_none().0, id.to_glib_none().0)) + } + } + + fn internal_set_testing(&self, testing: bool) { + unsafe { + ffi::rsvg_handle_internal_set_testing(self.to_glib_none().0, testing.to_glib()); + } + } + + //fn read_stream_sync<'a, P: IsA</*Ignored*/gio::InputStream>, Q: Into<Option<&'a /*Ignored*/gio::Cancellable>>>(&self, stream: &P, cancellable: Q) -> Result<(), Error> { + // unsafe { TODO: call ffi::rsvg_handle_read_stream_sync() } + //} + + fn render_cairo(&self, cr: &cairo::Context) -> bool { + unsafe { + from_glib(ffi::rsvg_handle_render_cairo(self.to_glib_none().0, mut_override(cr.to_glib_none().0))) + } + } + + fn render_cairo_sub<'a, P: Into<Option<&'a str>>>(&self, cr: &cairo::Context, id: P) -> bool { + let id = id.into(); + let id = id.to_glib_none(); + unsafe { + from_glib(ffi::rsvg_handle_render_cairo_sub(self.to_glib_none().0, mut_override(cr.to_glib_none().0), id.0)) + } + } + + //fn set_base_gfile<P: IsA</*Ignored*/gio::File>>(&self, base_file: &P) { + // unsafe { TODO: call ffi::rsvg_handle_set_base_gfile() } + //} + + fn set_base_uri(&self, base_uri: &str) { + unsafe { + ffi::rsvg_handle_set_base_uri(self.to_glib_none().0, base_uri.to_glib_none().0); + } + } + + fn set_dpi(&self, dpi: f64) { + unsafe { + ffi::rsvg_handle_set_dpi(self.to_glib_none().0, dpi); + } + } + + fn set_dpi_x_y(&self, dpi_x: f64, dpi_y: f64) { + unsafe { + ffi::rsvg_handle_set_dpi_x_y(self.to_glib_none().0, dpi_x, dpi_y); + } + } + + fn write(&self, buf: &[u8]) -> Result<(), Error> { + let count = buf.len() as usize; + unsafe { + let mut error = ptr::null_mut(); + let _ = ffi::rsvg_handle_write(self.to_glib_none().0, buf.to_glib_none().0, count, &mut error); + if error.is_null() { Ok(()) } else { Err(from_glib_full(error)) } + } + } + + fn get_property_dpi_x(&self) -> f64 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <f64 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "dpi-x".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn set_property_dpi_x(&self, dpi_x: f64) { + unsafe { + gobject_ffi::g_object_set_property(self.to_glib_none().0, "dpi-x".to_glib_none().0, Value::from(&dpi_x).to_glib_none().0); + } + } + + fn get_property_dpi_y(&self) -> f64 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <f64 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "dpi-y".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn set_property_dpi_y(&self, dpi_y: f64) { + unsafe { + gobject_ffi::g_object_set_property(self.to_glib_none().0, "dpi-y".to_glib_none().0, Value::from(&dpi_y).to_glib_none().0); + } + } + + fn get_property_em(&self) -> f64 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <f64 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "em".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn get_property_ex(&self) -> f64 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <f64 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "ex".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn get_property_flags(&self) -> HandleFlags { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <HandleFlags as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "flags".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn get_property_height(&self) -> i32 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <i32 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "height".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn get_property_width(&self) -> i32 { + unsafe { + let mut value = Value::uninitialized(); + gobject_ffi::g_value_init(value.to_glib_none_mut().0, <i32 as StaticType>::static_type().to_glib()); + gobject_ffi::g_object_get_property(self.to_glib_none().0, "width".to_glib_none().0, value.to_glib_none_mut().0); + value.get().unwrap() + } + } + + fn connect_property_dpi_x_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::dpi-x", + transmute(notify_dpi_x_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_dpi_y_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::dpi-y", + transmute(notify_dpi_y_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_em_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::em", + transmute(notify_em_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_ex_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::ex", + transmute(notify_ex_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_flags_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::flags", + transmute(notify_flags_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_height_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::height", + transmute(notify_height_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } + + fn connect_property_width_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_<Box_<Fn(&Self) + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "notify::width", + transmute(notify_width_trampoline::<Self> as usize), Box_::into_raw(f) as *mut _) + } + } +} + +unsafe extern "C" fn notify_dpi_x_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_dpi_y_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_em_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_ex_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_flags_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_height_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} + +unsafe extern "C" fn notify_width_trampoline<P>(this: *mut ffi::RsvgHandle, _param_spec: glib_ffi::gpointer, f: glib_ffi::gpointer) +where P: IsA<Handle> { + callback_guard!(); + let f: &&(Fn(&P) + 'static) = transmute(f); + f(&Handle::from_glib_borrow(this).downcast_unchecked()) +} diff --git a/rsvg-rs/src/auto/mod.rs b/rsvg-rs/src/auto/mod.rs new file mode 100644 index 00000000..4ddf345a --- /dev/null +++ b/rsvg-rs/src/auto/mod.rs @@ -0,0 +1,14 @@ +// This file was generated by gir (d50d839) from gir-files (???) +// DO NOT EDIT + +mod handle; +pub use self::handle::Handle; +pub use self::handle::HandleExt; + +mod flags; +pub use self::flags::HandleFlags; + +#[doc(hidden)] +pub mod traits { + pub use super::HandleExt; +} diff --git a/rsvg-rs/src/dimension_data.rs b/rsvg-rs/src/dimension_data.rs new file mode 100644 index 00000000..37dc22c4 --- /dev/null +++ b/rsvg-rs/src/dimension_data.rs @@ -0,0 +1,67 @@ +use std::mem; +use glib::translate::*; +use ffi; + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +pub struct DimensionData { + pub width: i32, + pub height: i32, + pub em: f64, + pub ex: f64, +} + +impl DimensionData { + pub fn new(width: i32, height: i32, em: f64, ex: f64) -> DimensionData { + DimensionData { + width: width, + height: height, + em: em, + ex: ex, + } + } +} + +#[doc(hidden)] +impl Uninitialized for DimensionData { + #[inline] + unsafe fn uninitialized() -> Self { + mem::uninitialized() + } +} + +#[doc(hidden)] +impl<'a> ToGlibPtr<'a, *const ffi::RsvgDimensionData> for DimensionData { + type Storage = &'a Self; + + #[inline] + fn to_glib_none(&'a self) -> Stash<'a, *const ffi::RsvgDimensionData, Self> { + let ptr: *const DimensionData = &*self; + Stash(ptr as *const ffi::RsvgDimensionData, self) + } +} + +#[doc(hidden)] +impl<'a> ToGlibPtrMut<'a, *mut ffi::RsvgDimensionData> for DimensionData { + type Storage = &'a mut Self; + + #[inline] + fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::RsvgDimensionData, Self> { + let ptr: *mut DimensionData = &mut *self; + StashMut(ptr as *mut ffi::RsvgDimensionData, self) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*const ffi::RsvgDimensionData> for DimensionData { + unsafe fn from_glib_none(ptr: *const ffi::RsvgDimensionData) -> Self { + *(ptr as *const DimensionData) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*mut ffi::RsvgDimensionData> for DimensionData { + unsafe fn from_glib_none(ptr: *mut ffi::RsvgDimensionData) -> Self { + *(ptr as *mut DimensionData) + } +}
\ No newline at end of file diff --git a/rsvg-rs/src/handle.rs b/rsvg-rs/src/handle.rs new file mode 100644 index 00000000..0e02e472 --- /dev/null +++ b/rsvg-rs/src/handle.rs @@ -0,0 +1,16 @@ +use ffi; +use std::ptr; + +use glib::Error; +use glib::translate::*; +use auto::Handle; + +impl Handle { + pub fn new_from_str(data: &str) -> Result<Handle, Error> { + unsafe { + let mut error = ptr::null_mut(); + let handle = ffi::rsvg_handle_new_from_data(data.as_ptr() as *mut _, data.len() as _, &mut error); + if error.is_null() { Ok(from_glib_full(handle)) } else { Err(from_glib_full(error)) } + } + } +}
\ No newline at end of file diff --git a/rsvg-rs/src/lib.rs b/rsvg-rs/src/lib.rs new file mode 100644 index 00000000..158eef54 --- /dev/null +++ b/rsvg-rs/src/lib.rs @@ -0,0 +1,125 @@ +extern crate rsvg_sys as ffi; +extern crate glib_sys as glib_ffi; +extern crate gobject_sys as gobject_ffi; + +#[macro_use] +extern crate glib; +extern crate cairo; +extern crate gdk_pixbuf; +#[macro_use] +extern crate bitflags; +extern crate libc; + +macro_rules! callback_guard { + () => () +} + +pub use glib::Error; + +mod auto; +pub use auto::*; + +mod handle; +mod position_data; +mod dimension_data; +pub use position_data::PositionData; +pub use dimension_data::DimensionData; + +#[cfg(test)] +#[macro_use] +extern crate imageproc; + +#[cfg(test)] +mod tests { + extern crate image; + + use super::HandleExt; + use self::image::GenericImage; + + fn get_fixture_path(fixture: &str) -> String { + return format!("./test-fixtures/{}", fixture); + } + + #[test] + fn it_should_be_possible_to_create_new_handle_and_write_manually_to_it() { + let handle = super::Handle::new(); + + handle.write(r#"<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="50" height="50"></svg>"#.as_bytes()).unwrap(); + handle.close().unwrap(); + + assert_eq!(handle.get_dimensions(), super::DimensionData { width: 50, height: 50, em: 50.0, ex: 50.0 }); + assert_eq!(handle.get_position_sub("#unknownid"), None); + } + + #[test] + fn it_should_be_possible_to_load_svg_from_string() { + let svg = r#"<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="50" height="50"></svg>"#; + let handle = super::Handle::new_from_str(svg).unwrap(); + + assert_eq!(handle.get_dimensions(), super::DimensionData { width: 50, height: 50, em: 50.0, ex: 50.0 }); + assert_eq!(handle.get_position_sub("#unknownid"), None); + } + + #[test] + fn it_should_be_possible_to_load_svg_from_slice() { + let svg = r#"<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="50" height="50"></svg>"#; + let handle = super::Handle::new_from_data(svg.as_bytes()).unwrap(); + + assert_eq!(handle.get_dimensions(), super::DimensionData { width: 50, height: 50, em: 50.0, ex: 50.0 }); + assert_eq!(handle.get_position_sub("#unknownid"), None); + } + + #[test] + #[ignore] + fn it_should_be_possible_to_load_svg_from_file() { + let svg_path = get_fixture_path("mysvg.svg"); + let handle = super::Handle::new_from_file(&svg_path).unwrap(); + + assert_eq!(handle.get_dimensions(), super::DimensionData { width: 100, height: 100, em: 100.0, ex: 100.0 }); + assert_eq!(handle.get_position_sub("#unknownid"), None); + } + + #[test] + #[ignore] + fn it_should_be_possible_to_render_to_cairo_context() { + let svg_path = get_fixture_path("mysvg.svg"); + let expected = image::open(get_fixture_path("mysvg.svg.png")).unwrap(); + let handle = super::Handle::new_from_file(&svg_path).unwrap(); + let dimensions = handle.get_dimensions(); + let surface = super::cairo::ImageSurface::create(super::cairo::Format::ARgb32, dimensions.width, dimensions.height).unwrap(); + let context = super::cairo::Context::new(&surface); + let mut png_data: Vec<u8> = vec!(); + + context.paint_with_alpha(0.0); + handle.render_cairo(&context); + surface.write_to_png(&mut png_data).unwrap(); + + let result = image::load_from_memory_with_format(&png_data, image::ImageFormat::PNG).unwrap(); + assert_dimensions_match!(result, expected); + assert_pixels_eq!(result, expected); + } + + #[test] + #[ignore] + fn it_should_be_possible_to_render_to_gdk_pixbuf_without_throwing() { + let svg_path = get_fixture_path("mysvg.svg"); + let expected = image::open(get_fixture_path("mysvg.svg.png")).unwrap(); + let handle = super::Handle::new_from_file(&svg_path).unwrap(); + let pixbuf = handle.get_pixbuf().unwrap(); + let pixels = (unsafe { pixbuf.get_pixels() }).to_vec(); + let dimensions = handle.get_dimensions(); + let result = image::ImageBuffer::from_raw(dimensions.width as u32, dimensions.height as u32, pixels) + .map(|v| image::DynamicImage::ImageRgba8(v)) + .unwrap(); + + assert_dimensions_match!(result, expected); + assert_pixels_eq!(result, expected); + } + + #[test] + fn it_should_return_an_error_when_loading_non_existing_file() { + let handle = super::Handle::new_from_file("unknown.svg"); + + assert!(handle.is_err()); + } +} diff --git a/rsvg-rs/src/position_data.rs b/rsvg-rs/src/position_data.rs new file mode 100644 index 00000000..10837ddd --- /dev/null +++ b/rsvg-rs/src/position_data.rs @@ -0,0 +1,67 @@ +use std::mem; +use glib::translate::*; +use ffi; + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +pub struct PositionData { + pub x: i32, + pub y: i32, + pub em: f64, + pub ex: f64, +} + +impl PositionData { + pub fn new(x: i32, y: i32, em: f64, ex: f64) -> PositionData { + PositionData { + x: x, + y: y, + em: em, + ex: ex, + } + } +} + +#[doc(hidden)] +impl Uninitialized for PositionData { + #[inline] + unsafe fn uninitialized() -> Self { + mem::uninitialized() + } +} + +#[doc(hidden)] +impl<'a> ToGlibPtr<'a, *const ffi::RsvgPositionData> for PositionData { + type Storage = &'a Self; + + #[inline] + fn to_glib_none(&'a self) -> Stash<'a, *const ffi::RsvgPositionData, Self> { + let ptr: *const PositionData = &*self; + Stash(ptr as *const ffi::RsvgPositionData, self) + } +} + +#[doc(hidden)] +impl<'a> ToGlibPtrMut<'a, *mut ffi::RsvgPositionData> for PositionData { + type Storage = &'a mut Self; + + #[inline] + fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::RsvgPositionData, Self> { + let ptr: *mut PositionData = &mut *self; + StashMut(ptr as *mut ffi::RsvgPositionData, self) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*const ffi::RsvgPositionData> for PositionData { + unsafe fn from_glib_none(ptr: *const ffi::RsvgPositionData) -> Self { + *(ptr as *const PositionData) + } +} + +#[doc(hidden)] +impl FromGlibPtrNone<*mut ffi::RsvgPositionData> for PositionData { + unsafe fn from_glib_none(ptr: *mut ffi::RsvgPositionData) -> Self { + *(ptr as *mut PositionData) + } +}
\ No newline at end of file |