[librsvg] LoadOptions: new struct to represent RsvgHandleFlags in the Rust code



commit cda7477f1358a54fc7704e80612a5b99bc945245
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Dec 17 15:57:19 2018 -0600

    LoadOptions: new struct to represent RsvgHandleFlags in the Rust code

 librsvg/rsvg-handle.c           | 25 ++++--------
 librsvg/rsvg-private.h          | 10 +----
 rsvg_internals/src/handle.rs    | 87 ++++++++++++++++++++++++++++++++---------
 rsvg_internals/src/lib.rs       |  2 +
 rsvg_internals/src/load.rs      | 15 +++----
 rsvg_internals/src/xml.rs       |  4 +-
 rsvg_internals/src/xml2_load.rs | 23 +++++------
 7 files changed, 101 insertions(+), 65 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 3762bc63..1832c131 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -141,13 +141,15 @@ extern GFile *rsvg_handle_rust_get_base_gfile (RsvgHandleRust *raw_handle);
 extern RsvgNode *rsvg_handle_defs_lookup (RsvgHandle *handle, const char *name);
 extern gboolean rsvg_handle_rust_node_is_root(RsvgHandleRust *raw_handle, RsvgNode *node);
 extern void rsvg_handle_rust_steal_result (RsvgHandleRust *raw_handle, RsvgXmlState *xml);
+extern guint rsvg_handle_rust_get_flags (RsvgHandleRust *raw_handle);
+extern void rsvg_handle_rust_set_flags (RsvgHandleRust *raw_handle, guint flags);
 
 /* Implemented in rsvg_internals/src/xml.rs */
 extern void rsvg_xml_state_free (RsvgXmlState *xml);
 extern gboolean rsvg_xml_state_tree_is_valid(RsvgXmlState *xml, GError **error);
 
 /* Implemented in rsvg_internals/src/load.rs */
-extern RsvgLoad *rsvg_load_new (RsvgXmlState *xml, gboolean unlimited_size) G_GNUC_WARN_UNUSED_RESULT;
+extern RsvgLoad *rsvg_load_new (RsvgXmlState *xml, guint flags) G_GNUC_WARN_UNUSED_RESULT;
 extern RsvgXmlState *rsvg_load_free (RsvgLoad *load) G_GNUC_WARN_UNUSED_RESULT;
 extern void rsvg_load_write (RsvgLoad *load, const guchar *buf, gsize count);
 extern gboolean rsvg_load_close (RsvgLoad *load, GError **error) G_GNUC_WARN_UNUSED_RESULT;
@@ -201,7 +203,6 @@ rsvg_handle_init (RsvgHandle * self)
 {
     self->priv = rsvg_handle_get_instance_private (self);
 
-    self->priv->flags = RSVG_HANDLE_FLAGS_NONE;
     self->priv->hstate = RSVG_HANDLE_STATE_START;
 
     self->priv->in_loop = FALSE;
@@ -252,7 +253,7 @@ rsvg_handle_set_property (GObject * instance, guint prop_id, GValue const *value
 
     switch (prop_id) {
     case PROP_FLAGS:
-        self->priv->flags = g_value_get_flags (value);
+        rsvg_handle_rust_set_flags (self->priv->rust_handle, g_value_get_flags (value));
         break;
     case PROP_DPI_X:
         rsvg_handle_rust_set_dpi_x (self->priv->rust_handle, g_value_get_double (value));
@@ -276,7 +277,7 @@ rsvg_handle_get_property (GObject * instance, guint prop_id, GValue * value, GPa
 
     switch (prop_id) {
     case PROP_FLAGS:
-        g_value_set_flags (value, self->priv->flags);
+        g_value_set_flags (value, rsvg_handle_rust_get_flags (self->priv->rust_handle));
         break;
     case PROP_DPI_X:
         g_value_set_double (value, rsvg_handle_rust_get_dpi_x (self->priv->rust_handle));
@@ -686,7 +687,7 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
     if (priv->hstate == RSVG_HANDLE_STATE_START) {
         priv->hstate = RSVG_HANDLE_STATE_LOADING;
         priv->load = rsvg_load_new (rsvg_xml_state_new (handle),
-                                    (priv->flags && RSVG_HANDLE_FLAG_UNLIMITED) != 0);
+                                    rsvg_handle_rust_get_flags (priv->rust_handle));
     }
 
     g_assert (priv->hstate == RSVG_HANDLE_STATE_LOADING);
@@ -822,7 +823,7 @@ rsvg_handle_read_stream_sync (RsvgHandle   *handle,
     xml = rsvg_xml_state_new (handle);
     read_successfully = rsvg_xml_state_load_from_possibly_compressed_stream (
         xml,
-        (priv->flags && RSVG_HANDLE_FLAG_UNLIMITED) != 0,
+        rsvg_handle_rust_get_flags (priv->rust_handle),
         stream,
         cancellable,
         error
@@ -1048,24 +1049,12 @@ rsvg_handle_get_desc (RsvgHandle * handle)
     return NULL;
 }
 
-guint
-rsvg_handle_get_flags (RsvgHandle *handle)
-{
-    return (guint) handle->priv->flags;
-}
-
 RsvgHandleRust *
 rsvg_handle_get_rust (RsvgHandle *handle)
 {
     return handle->priv->rust_handle;
 }
 
-gboolean
-rsvg_handle_keep_image_data (RsvgHandle *handle)
-{
-    return (handle->priv->flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0;
-}
-
 static RsvgDrawingCtx *
 rsvg_handle_create_drawing_ctx(RsvgHandle *handle,
                                cairo_t *cr,
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 3d4afc40..57046e1e 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -89,8 +89,6 @@ typedef struct RsvgLoad RsvgLoad;
 typedef struct RsvgHandleRust RsvgHandleRust;
 
 struct RsvgHandlePrivate {
-    RsvgHandleFlags flags;
-
     RsvgHandleState hstate;
 
     RsvgLoad *load;
@@ -126,7 +124,7 @@ void rsvg_xml_state_error(RsvgXmlState *xml, const char *msg);
 /* Implemented in rsvg_internals/src/xml2_load.rs */
 G_GNUC_INTERNAL
 gboolean rsvg_xml_state_load_from_possibly_compressed_stream (RsvgXmlState *xml,
-                                                              gboolean      unlimited_size,
+                                                              guint         flags,
                                                               GInputStream *stream,
                                                               GCancellable *cancellable,
                                                               GError      **error);
@@ -138,15 +136,9 @@ G_GNUC_INTERNAL
 void rsvg_return_if_fail_warning (const char *pretty_function,
                                   const char *expression, GError ** error);
 
-G_GNUC_INTERNAL
-guint rsvg_handle_get_flags (RsvgHandle *handle);
-
 G_GNUC_INTERNAL
 RsvgHandleRust *rsvg_handle_get_rust (RsvgHandle *handle);
 
-G_GNUC_INTERNAL
-gboolean rsvg_handle_keep_image_data (RsvgHandle *handle);
-
 /* Implemented in rsvg_internals/src/handle.rs */
 G_GNUC_INTERNAL
 char *rsvg_handle_acquire_data (RsvgHandle *handle,
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index 24eeac4d..a14dfdfa 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,4 +1,4 @@
-use std::cell::{Ref, RefCell};
+use std::cell::{Cell, Ref, RefCell};
 use std::error::Error;
 use std::ptr;
 use std::rc::Rc;
@@ -31,10 +31,24 @@ pub struct RsvgHandle {
     _private: [u8; 0],
 }
 
+/// Flags used during loading
+///
+/// We communicate these to/from the C code with a guint <-> u32,
+/// and this struct provides to_flags() and from_flags() methods.
+#[derive(Default, Copy, Clone)]
+pub struct LoadOptions {
+    /// Whether to turn off size limits in libxml2
+    pub unlimited_size: bool,
+
+    /// Whether to keep original (undecoded) image data to embed in Cairo PDF surfaces
+    pub keep_image_data: bool,
+}
+
 pub struct Handle {
     dpi: Dpi,
     base_url: RefCell<Option<Url>>,
     svg: RefCell<Option<Svg>>,
+    load_options: Cell<LoadOptions>,
 }
 
 impl Handle {
@@ -43,14 +57,45 @@ impl Handle {
             dpi: Dpi::default(),
             base_url: RefCell::new(None),
             svg: RefCell::new(None),
+            load_options: Cell::new(LoadOptions::default()),
+        }
+    }
+}
+
+// Keep these in sync with rsvg.h:RsvgHandleFlags
+const RSVG_HANDLE_FLAG_UNLIMITED: u32 = 1 << 0;
+const RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA: u32 = 1 << 1;
+
+pub fn get_load_options(handle: *const RsvgHandle) -> LoadOptions {
+    let rhandle = get_rust_handle(handle);
+    rhandle.load_options.get()
+}
+
+impl LoadOptions {
+    pub fn from_flags(flags: u32) -> Self {
+        LoadOptions {
+            unlimited_size: (flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0,
+            keep_image_data: (flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0,
+        }
+    }
+
+    fn to_flags(&self) -> u32 {
+        let mut flags = 0;
+
+        if self.unlimited_size {
+            flags |= RSVG_HANDLE_FLAG_UNLIMITED;
+        }
+
+        if self.keep_image_data {
+            flags |= RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA;
         }
+
+        flags
     }
 }
 
 #[allow(improper_ctypes)]
 extern "C" {
-    fn rsvg_handle_get_flags(handle: *const RsvgHandle) -> u32;
-
     fn rsvg_handle_new_from_gfile_sync(
         file: *const gio_sys::GFile,
         flags: u32,
@@ -58,8 +103,6 @@ extern "C" {
         error: *mut *mut glib_sys::GError,
     ) -> *mut RsvgHandle;
 
-    fn rsvg_handle_keep_image_data(handle: *const RsvgHandle) -> glib_sys::gboolean;
-
     fn rsvg_handle_get_rust(handle: *const RsvgHandle) -> *mut Handle;
 }
 
@@ -88,11 +131,13 @@ pub fn lookup_fragment_id(handle: *const RsvgHandle, fragment: &Fragment) -> Opt
 
 pub fn load_extern(handle: *const RsvgHandle, aurl: &AllowedUrl) -> Result<*const RsvgHandle, ()> {
     unsafe {
+        let rhandle = get_rust_handle(handle);
+
         let file = GFile::new_for_uri(aurl.url().as_str());
 
         let res = rsvg_handle_new_from_gfile_sync(
             file.to_glib_none().0,
-            rsvg_handle_get_flags(handle),
+            rhandle.load_options.get().to_flags(),
             ptr::null(),
             ptr::null_mut(),
         );
@@ -112,12 +157,6 @@ pub fn load_extern(handle: *const RsvgHandle, aurl: &AllowedUrl) -> Result<*cons
     }
 }
 
-const RSVG_HANDLE_FLAG_UNLIMITED: u32 = 1 << 0;
-
-pub fn get_unlimited_size(handle: *const RsvgHandle) -> bool {
-    unsafe { (rsvg_handle_get_flags(handle) & RSVG_HANDLE_FLAG_UNLIMITED) != 0 }
-}
-
 pub fn get_dpi<'a>(handle: *const RsvgHandle) -> &'a Dpi {
     let rhandle = get_rust_handle(handle);
 
@@ -149,14 +188,12 @@ pub fn acquire_stream(
     io::acquire_stream(&aurl, None)
 }
 
-fn keep_image_data(handle: *const RsvgHandle) -> bool {
-    unsafe { from_glib(rsvg_handle_keep_image_data(handle)) }
-}
-
 pub fn load_image_to_surface(
     handle: *mut RsvgHandle,
     aurl: &AllowedUrl,
 ) -> Result<ImageSurface, LoadingError> {
+    let rhandle = get_rust_handle(handle);
+
     let data = acquire_data(handle, aurl)?;
 
     if data.data.len() == 0 {
@@ -176,7 +213,7 @@ pub fn load_image_to_surface(
 
     let surface = SharedImageSurface::from_pixbuf(&pixbuf)?.into_image_surface()?;
 
-    if keep_image_data(handle) {
+    if rhandle.load_options.get().keep_image_data {
         if let Some(mime_type) = data.content_type {
             extern "C" {
                 fn cairo_surface_set_mime_data(
@@ -270,7 +307,7 @@ pub unsafe extern "C" fn rsvg_handle_rust_free(raw_handle: *mut Handle) {
     Box::from_raw(raw_handle);
 }
 
-fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a mut Handle {
+pub fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a mut Handle {
     unsafe { &mut *(rsvg_handle_get_rust(handle) as *mut Handle) }
 }
 
@@ -519,3 +556,17 @@ pub unsafe extern "C" fn rsvg_handle_rust_node_is_root(
 
     Rc::ptr_eq(&svg.tree.root(), node).to_glib()
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_get_flags(raw_handle: *const Handle) -> u32 {
+    let rhandle = &*raw_handle;
+
+    rhandle.load_options.get().to_flags()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_set_flags(raw_handle: *const Handle, flags: u32) {
+    let rhandle = &*raw_handle;
+
+    rhandle.load_options.set(LoadOptions::from_flags(flags));
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 6fd85a12..a7950025 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -52,12 +52,14 @@ pub use handle::{
     rsvg_handle_rust_get_base_gfile,
     rsvg_handle_rust_get_dpi_x,
     rsvg_handle_rust_get_dpi_y,
+    rsvg_handle_rust_get_flags,
     rsvg_handle_rust_get_root,
     rsvg_handle_rust_new,
     rsvg_handle_rust_node_is_root,
     rsvg_handle_rust_set_base_url,
     rsvg_handle_rust_set_dpi_x,
     rsvg_handle_rust_set_dpi_y,
+    rsvg_handle_rust_set_flags,
     rsvg_handle_rust_steal_result,
 };
 
diff --git a/rsvg_internals/src/load.rs b/rsvg_internals/src/load.rs
index 69a318a4..a112b02b 100644
--- a/rsvg_internals/src/load.rs
+++ b/rsvg_internals/src/load.rs
@@ -6,6 +6,7 @@ use glib_sys;
 use std::slice;
 
 use error::set_gerror;
+use handle::LoadOptions;
 use xml::XmlState;
 use xml2_load::{xml_state_load_from_possibly_compressed_stream, ParseFromStreamError};
 
@@ -18,7 +19,7 @@ use xml2_load::{xml_state_load_from_possibly_compressed_stream, ParseFromStreamE
 // This struct maintains the loading context while an RsvgHandle is being
 // populated with data, in case the caller is using write()/close().
 pub struct LoadContext<'a> {
-    unlimited_size: bool,
+    load_options: LoadOptions,
 
     state: LoadState,
 
@@ -35,9 +36,9 @@ enum LoadState {
 }
 
 impl<'a> LoadContext<'a> {
-    pub fn new(xml: &mut XmlState, unlimited_size: bool) -> LoadContext {
+    pub fn new(xml: &mut XmlState, load_options: LoadOptions) -> LoadContext {
         LoadContext {
-            unlimited_size,
+            load_options,
             state: LoadState::Start,
             buffer: Vec::new(),
             xml,
@@ -74,7 +75,7 @@ impl<'a> LoadContext<'a> {
 
                 xml_state_load_from_possibly_compressed_stream(
                     &mut self.xml,
-                    self.unlimited_size,
+                    &self.load_options,
                     stream.upcast(),
                     None,
                 )
@@ -86,14 +87,14 @@ impl<'a> LoadContext<'a> {
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_load_new<'a>(
     raw_xml: *mut XmlState,
-    unlimited_size: glib_sys::gboolean,
+    flags: u32,
 ) -> *mut LoadContext<'a> {
     assert!(!raw_xml.is_null());
 
     let xml = &mut *raw_xml;
-    let unlimited_size = from_glib(unlimited_size);
+    let load_options = LoadOptions::from_flags(flags);
 
-    Box::into_raw(Box::new(LoadContext::new(xml, unlimited_size)))
+    Box::into_raw(Box::new(LoadContext::new(xml, load_options)))
 }
 
 #[no_mangle]
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index 1eeb8c82..af4e5133 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -516,10 +516,10 @@ impl XmlState {
             _ => AcquireError::ResourceError,
         })?;
 
-        let unlimited_size = handle::get_unlimited_size(self.handle);
+        let load_options = handle::get_load_options(self.handle);
 
         // FIXME: pass a cancellable
-        xml_state_parse_from_stream(self, unlimited_size, stream, None).map_err(|e| match e {
+        xml_state_parse_from_stream(self, &load_options, stream, None).map_err(|e| match e {
             ParseFromStreamError::CouldNotCreateParser => AcquireError::FatalError,
             ParseFromStreamError::IoError(_) => AcquireError::ResourceError,
             ParseFromStreamError::XmlParseError(_) => AcquireError::FatalError,
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index 63eb61a0..cfb59df1 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -15,6 +15,7 @@ use std::str;
 use glib::translate::*;
 
 use error::set_gerror;
+use handle::LoadOptions;
 use io::get_input_stream_for_loading;
 use property_bag::PropertyBag;
 use util::utf8_cstr;
@@ -189,10 +190,10 @@ unsafe extern "C" fn sax_get_parameter_entity_cb(
     sax_get_entity_cb(ctx, name)
 }
 
-fn set_xml_parse_options(parser: xmlParserCtxtPtr, unlimited_size: bool) {
+fn set_xml_parse_options(parser: xmlParserCtxtPtr, load_options: &LoadOptions) {
     let mut options: libc::c_int = XML_PARSE_NONET | XML_PARSE_BIG_LINES;
 
-    if unlimited_size {
+    if load_options.unlimited_size {
         options |= XML_PARSE_HUGE;
     }
 
@@ -286,7 +287,7 @@ struct Xml2Parser {
 impl Xml2Parser {
     fn from_stream(
         xml: &mut XmlState,
-        unlimited_size: bool,
+        load_options: &LoadOptions,
         stream: gio::InputStream,
         cancellable: Option<&gio::Cancellable>,
     ) -> Result<Xml2Parser, ParseFromStreamError> {
@@ -322,7 +323,7 @@ impl Xml2Parser {
                 // stream_ctx_close function
                 Err(ParseFromStreamError::CouldNotCreateParser)
             } else {
-                set_xml_parse_options(parser, unlimited_size);
+                set_xml_parse_options(parser, load_options);
                 Ok(Xml2Parser { parser, gio_error })
             }
         }
@@ -402,30 +403,30 @@ pub enum ParseFromStreamError {
 // for example, when including another XML file via xi:include.
 pub fn xml_state_parse_from_stream(
     xml: &mut XmlState,
-    unlimited_size: bool,
+    load_options: &LoadOptions,
     stream: gio::InputStream,
     cancellable: Option<&gio::Cancellable>,
 ) -> Result<(), ParseFromStreamError> {
-    Xml2Parser::from_stream(xml, unlimited_size, stream, cancellable)
+    Xml2Parser::from_stream(xml, load_options, stream, cancellable)
         .and_then(|parser| parser.parse())
 }
 
 pub fn xml_state_load_from_possibly_compressed_stream(
     xml: &mut XmlState,
-    unlimited_size: bool,
+    load_options: &LoadOptions,
     stream: gio::InputStream,
     cancellable: Option<gio::Cancellable>,
 ) -> Result<(), ParseFromStreamError> {
     let stream = get_input_stream_for_loading(stream, cancellable.as_ref())
         .map_err(|e| ParseFromStreamError::IoError(e))?;
 
-    xml_state_parse_from_stream(xml, unlimited_size, stream, cancellable.as_ref())
+    xml_state_parse_from_stream(xml, load_options, stream, cancellable.as_ref())
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn rsvg_xml_state_load_from_possibly_compressed_stream(
     xml: *mut XmlState,
-    unlimited_size: glib_sys::gboolean,
+    flags: u32,
     stream: *mut gio_sys::GInputStream,
     cancellable: *mut gio_sys::GCancellable,
     error: *mut *mut glib_sys::GError,
@@ -433,12 +434,12 @@ pub unsafe extern "C" fn rsvg_xml_state_load_from_possibly_compressed_stream(
     assert!(!xml.is_null());
     let xml = &mut *xml;
 
-    let unlimited_size = from_glib(unlimited_size);
+    let load_options = LoadOptions::from_flags(flags);
 
     let stream = from_glib_none(stream);
     let cancellable = from_glib_none(cancellable);
 
-    match xml_state_load_from_possibly_compressed_stream(xml, unlimited_size, stream, cancellable) {
+    match xml_state_load_from_possibly_compressed_stream(xml, &load_options, stream, cancellable) {
         Ok(()) => true.to_glib(),
 
         Err(e) => {


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