[librsvg: 3/12] state: move conditional processing to rust



commit a6f72224dcc282c4679d05433cde12fef9d2184f
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Apr 21 15:33:08 2018 +0200

    state: move conditional processing to rust
    
    Note that the state cond now is a plain bool, not an Option<bool>
    even if the C code had a has_cond field. As far as I can see there
    is no reason to distinguish between cond being set to true and cond
    being unset.

 librsvg/rsvg-styles.c           | 69 +++------------------------------------
 librsvg/rsvg-styles.h           |  9 ------
 rsvg_internals/src/cond.rs      | 49 ++--------------------------
 rsvg_internals/src/lib.rs       |  7 +---
 rsvg_internals/src/state.rs     | 72 ++++++++++++++++++++++++++++++++++-------
 rsvg_internals/src/structure.rs |  4 +--
 rsvg_internals/src/text.rs      |  2 +-
 7 files changed, 70 insertions(+), 142 deletions(-)
---
diff --git a/librsvg/rsvg-styles.c b/librsvg/rsvg-styles.c
index 4e4d5ada..d5c860b5 100644
--- a/librsvg/rsvg-styles.c
+++ b/librsvg/rsvg-styles.c
@@ -58,6 +58,9 @@ extern gboolean rsvg_state_rust_parse_style_pair(State *state, RsvgAttribute att
 
 extern void rsvg_state_rust_inherit_run(State *dst, State *src, InheritanceFunction inherit_fn, gboolean 
inherituninheritables);
 
+extern gboolean rsvg_state_parse_conditional_processing_attributes (RsvgState *state, RsvgPropertyBag *pbag)
+    G_GNUC_WARN_UNUSED_RESULT;
+
 typedef struct _StyleValueData {
     gchar *value;
     gboolean important;
@@ -113,8 +116,6 @@ rsvg_state_init (RsvgState * state)
     state->flood_color = 0;
     state->flood_opacity = 255;
 
-    state->cond_true = TRUE;
-
     state->has_current_color = FALSE;
     state->has_flood_color = FALSE;
     state->has_flood_opacity = FALSE;
@@ -122,7 +123,6 @@ rsvg_state_init (RsvgState * state)
     state->has_fill_opacity = FALSE;
     state->has_stroke_server = FALSE;
     state->has_stroke_opacity = FALSE;
-    state->has_cond = FALSE;
     state->has_stop_color = FALSE;
     state->has_stop_opacity = FALSE;
 
@@ -246,8 +246,6 @@ rsvg_state_inherit_run (RsvgState * dst, const RsvgState * src,
             dst->stop_opacity = src->stop_opacity;
         }
     }
-    if (function (dst->has_cond, src->has_cond))
-        dst->cond_true = src->cond_true;
 
     rsvg_state_rust_inherit_run (dst->state_rust, src->state_rust, function, inherituninheritables);
 
@@ -533,53 +531,6 @@ rsvg_parse_style_pair (RsvgState *state,
     return success;
 }
 
-/* returns TRUE if this element should be processed according to <switch> semantics
-   http://www.w3.org/TR/SVG/struct.html#SwitchElement */
-static void
-rsvg_parse_conditional_processing_attributes (RsvgState * state, RsvgPropertyBag * atts)
-{
-    gboolean required_features_ok = TRUE;
-    gboolean required_extensions_ok = TRUE;
-    gboolean system_language_ok = TRUE;
-    gboolean has_cond = FALSE;
-
-    RsvgPropertyBagIter *iter;
-    const char *key;
-    RsvgAttribute attr;
-    const char *value;
-
-    iter = rsvg_property_bag_iter_begin (atts);
-
-    while (rsvg_property_bag_iter_next (iter, &key, &attr, &value)) {
-        switch (attr) {
-        case RSVG_ATTRIBUTE_REQUIRED_FEATURES:
-            required_features_ok = rsvg_cond_check_required_features (value);
-            has_cond = TRUE;
-            break;
-
-        case RSVG_ATTRIBUTE_REQUIRED_EXTENSIONS:
-            required_extensions_ok = rsvg_cond_check_required_extensions (value);
-            has_cond = TRUE;
-            break;
-
-        case RSVG_ATTRIBUTE_SYSTEM_LANGUAGE:
-            system_language_ok = rsvg_cond_check_system_language (value);
-            has_cond = TRUE;
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    rsvg_property_bag_iter_end (iter);
-
-    if (has_cond) {
-        state->cond_true = required_features_ok && required_extensions_ok && system_language_ok;
-        state->has_cond = TRUE;
-    }
-}
-
 /* take a pair of the form (fill="#ff00ff") and parse it as a style */
 void
 rsvg_parse_presentation_attributes (RsvgState * state, RsvgPropertyBag * atts)
@@ -988,7 +939,7 @@ rsvg_parse_style_attrs (RsvgHandle *handle,
     rsvg_parse_presentation_attributes (state, atts);
 
     /* TODO: i'm not sure it should reside here */
-    rsvg_parse_conditional_processing_attributes (state, atts);
+    success = success && rsvg_state_parse_conditional_processing_attributes (state, atts);
 
     /* Try to properly support all of the following, including inheritance:
      * *
@@ -1157,18 +1108,6 @@ rsvg_state_get_stroke_opacity (RsvgState *state)
     return state->stroke_opacity;
 }
 
-gboolean
-rsvg_state_get_cond_true (RsvgState *state)
-{
-    return state->cond_true;
-}
-
-void
-rsvg_state_set_cond_true (RsvgState *state, gboolean cond_true)
-{
-    state->cond_true = cond_true;
-}
-
 RsvgCssColorSpec *
 rsvg_state_get_stop_color (RsvgState *state)
 {
diff --git a/librsvg/rsvg-styles.h b/librsvg/rsvg-styles.h
index 4f48d341..7e426203 100644
--- a/librsvg/rsvg-styles.h
+++ b/librsvg/rsvg-styles.h
@@ -66,9 +66,6 @@ struct _RsvgState {
     RsvgOpacitySpec stop_opacity;
     gboolean has_stop_opacity;
 
-    gboolean has_cond;
-    gboolean cond_true;
-
     guint32 current_color;
     gboolean has_current_color;
 
@@ -148,12 +145,6 @@ RsvgPaintServer *rsvg_state_get_stroke (RsvgState *state);
 G_GNUC_INTERNAL
 guint8 rsvg_state_get_stroke_opacity (RsvgState *state);
 
-G_GNUC_INTERNAL
-gboolean rsvg_state_get_cond_true (RsvgState *state);
-
-G_GNUC_INTERNAL
-void rsvg_state_set_cond_true (RsvgState *state, gboolean cond_true);
-
 G_GNUC_INTERNAL
 RsvgCssColorSpec *rsvg_state_get_stop_color (RsvgState *state);
 
diff --git a/rsvg_internals/src/cond.rs b/rsvg_internals/src/cond.rs
index 6b79c2d9..5c30a95a 100644
--- a/rsvg_internals/src/cond.rs
+++ b/rsvg_internals/src/cond.rs
@@ -1,22 +1,15 @@
-use glib;
-use glib_sys;
-use libc;
-
 use error::*;
 use parsers::Parse;
 use std::marker::PhantomData;
-use util::utf8_cstr;
 
 #[allow(unused_imports)]
 use std::ascii::AsciiExt;
 
-use self::glib::translate::*;
-
 // No extensions at the moment.
 static IMPLEMENTED_EXTENSIONS: &[&str] = &[];
 
 #[derive(Debug, PartialEq)]
-struct RequiredExtensions(bool);
+pub struct RequiredExtensions(pub bool);
 
 impl Parse for RequiredExtensions {
     type Data = ();
@@ -58,7 +51,7 @@ static IMPLEMENTED_FEATURES: &[&str] = &[
 ];
 
 #[derive(Debug, PartialEq)]
-struct RequiredFeatures(bool);
+pub struct RequiredFeatures(pub bool);
 
 impl Parse for RequiredFeatures {
     type Data = ();
@@ -75,7 +68,7 @@ impl Parse for RequiredFeatures {
 }
 
 #[derive(Debug, PartialEq)]
-struct SystemLanguage<'a>(bool, PhantomData<&'a i8>);
+pub struct SystemLanguage<'a>(pub bool, pub PhantomData<&'a i8>);
 
 impl<'a> Parse for SystemLanguage<'a> {
     type Data = &'a [String];
@@ -106,42 +99,6 @@ impl<'a> Parse for SystemLanguage<'a> {
     }
 }
 
-#[no_mangle]
-pub extern "C" fn rsvg_cond_check_required_extensions(
-    raw_value: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let value = unsafe { utf8_cstr(raw_value) };
-
-    match RequiredExtensions::parse(value, ()) {
-        Ok(RequiredExtensions(res)) => res.to_glib(),
-        Err(_) => false.to_glib(),
-    }
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_cond_check_required_features(
-    raw_value: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let value = unsafe { utf8_cstr(raw_value) };
-
-    match RequiredFeatures::parse(value, ()) {
-        Ok(RequiredFeatures(res)) => res.to_glib(),
-        Err(_) => false.to_glib(),
-    }
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_cond_check_system_language(
-    raw_value: *const libc::c_char,
-) -> glib_sys::gboolean {
-    let value = unsafe { utf8_cstr(raw_value) };
-
-    match SystemLanguage::parse(value, &glib::get_language_names()) {
-        Ok(SystemLanguage(res, _)) => res.to_glib(),
-        Err(_) => false.to_glib(),
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 372b430d..0c3035ff 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -31,12 +31,6 @@ pub use cnode::{rsvg_rust_cnode_get_impl, rsvg_rust_cnode_new};
 
 pub use color::{rsvg_css_parse_color, AllowCurrentColor, AllowInherit, ColorKind, ColorSpec};
 
-pub use cond::{
-    rsvg_cond_check_required_extensions,
-    rsvg_cond_check_required_features,
-    rsvg_cond_check_system_language,
-};
-
 pub use draw::rsvg_cairo_add_clipping_rect;
 
 pub use drawing_ctx::{rsvg_drawing_ctx_state_pop, rsvg_drawing_ctx_state_push};
@@ -119,6 +113,7 @@ pub use shapes::{
 
 pub use state::{
     rsvg_state_is_visible,
+    rsvg_state_parse_conditional_processing_attributes,
     rsvg_state_reconstruct,
     rsvg_state_rust_clone,
     rsvg_state_rust_contains_important_style,
diff --git a/rsvg_internals/src/state.rs b/rsvg_internals/src/state.rs
index e6c4ca0c..7b977420 100644
--- a/rsvg_internals/src/state.rs
+++ b/rsvg_internals/src/state.rs
@@ -1,4 +1,5 @@
 use cairo::{self, MatrixTrait};
+use glib;
 use glib::translate::*;
 use glib_sys;
 use libc;
@@ -8,6 +9,7 @@ use std::ptr;
 
 use attributes::Attribute;
 use color::{Color, ColorSpec};
+use cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
 use error::*;
 use iri::IRI;
 use length::{Dasharray, LengthDir, RsvgLength};
@@ -15,6 +17,7 @@ use node::RsvgNode;
 use opacity::{Opacity, OpacitySpec};
 use paint_server::PaintServer;
 use parsers::Parse;
+use property_bag::PropertyBag;
 use property_macros::Property;
 use util::utf8_cstr;
 
@@ -75,6 +78,7 @@ pub struct State {
     pub xml_space: Option<XmlSpace>,
 
     important_styles: RefCell<HashSet<String>>,
+    cond: bool,
 }
 
 impl State {
@@ -121,6 +125,7 @@ impl State {
             xml_space: Default::default(),
 
             important_styles: Default::default(),
+            cond: true,
         }
     }
 
@@ -304,6 +309,34 @@ impl State {
 
         Ok(())
     }
+
+    pub fn parse_conditional_processing_attributes(
+        &mut self,
+        pbag: &PropertyBag,
+    ) -> Result<(), AttributeError> {
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::RequiredExtensions if self.cond => {
+                    self.cond =
+                        RequiredExtensions::parse(value, ()).map(|RequiredExtensions(res)| res)?;
+                }
+
+                Attribute::RequiredFeatures if self.cond => {
+                    self.cond =
+                        RequiredFeatures::parse(value, ()).map(|RequiredFeatures(res)| res)?;
+                }
+
+                Attribute::SystemLanguage if self.cond => {
+                    self.cond = SystemLanguage::parse(value, &glib::get_language_names())
+                        .map(|SystemLanguage(res, _)| res)?;
+                }
+
+                _ => {}
+            }
+        }
+
+        Ok(())
+    }
 }
 
 // Parses the `value` for the type `T` of the property, including `inherit` values.
@@ -329,8 +362,6 @@ extern "C" {
     fn rsvg_state_reinit(state: *mut RsvgState);
     fn rsvg_state_clone(state: *mut RsvgState, src: *const RsvgState);
     fn rsvg_state_parent(state: *const RsvgState) -> *mut RsvgState;
-    fn rsvg_state_get_cond_true(state: *const RsvgState) -> glib_sys::gboolean;
-    fn rsvg_state_set_cond_true(state: *const RsvgState, cond_true: glib_sys::gboolean);
     fn rsvg_state_get_stop_color(state: *const RsvgState) -> *const ColorSpec;
     fn rsvg_state_get_stop_opacity(state: *const RsvgState) -> *const OpacitySpec;
     fn rsvg_state_get_current_color(state: *const RsvgState) -> u32;
@@ -420,16 +451,6 @@ pub fn text_gravity_is_vertical(state: *const RsvgState) -> bool {
     }
 }
 
-pub fn get_cond_true(state: *const RsvgState) -> bool {
-    unsafe { from_glib(rsvg_state_get_cond_true(state)) }
-}
-
-pub fn set_cond_true(state: *const RsvgState, cond_true: bool) {
-    unsafe {
-        rsvg_state_set_cond_true(state, cond_true.to_glib());
-    }
-}
-
 pub fn get_stop_color(state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
     unsafe {
         let spec_ptr = rsvg_state_get_stop_color(state);
@@ -510,6 +531,16 @@ pub fn reinherit(state: *mut RsvgState, src: *const RsvgState) {
     }
 }
 
+pub fn get_cond(state: *mut RsvgState) -> bool {
+    get_state_rust(state).cond
+}
+
+pub fn set_cond(state: *mut RsvgState, value: bool) {
+    let rstate = get_state_rust(state);
+
+    rstate.cond = value;
+}
+
 pub fn get_state_rust<'a>(state: *const RsvgState) -> &'a mut State {
     unsafe { &mut *rsvg_state_get_state_rust(state) }
 }
@@ -960,6 +991,21 @@ pub extern "C" fn rsvg_state_is_visible(state: *const RsvgState) -> glib_sys::gb
     is_visible(state).to_glib()
 }
 
+#[no_mangle]
+pub extern "C" fn rsvg_state_parse_conditional_processing_attributes(
+    state: *mut RsvgState,
+    pbag: *const PropertyBag,
+) -> glib_sys::gboolean {
+    let state = unsafe { &mut *state };
+    let pbag = unsafe { &*pbag };
+
+    let rstate = get_state_rust(state);
+    match rstate.parse_conditional_processing_attributes(pbag) {
+        Ok(_) => true.to_glib(),
+        Err(_) => false.to_glib(),
+    }
+}
+
 // Rust State API for consumption from C ----------------------------------------
 
 #[no_mangle]
@@ -1100,6 +1146,8 @@ pub extern "C" fn rsvg_state_rust_inherit_run(
     inherit(inherit_fn, &mut dst.xml_lang, &src.xml_lang);
     inherit(inherit_fn, &mut dst.xml_space, &src.xml_space);
 
+    dst.cond = src.cond;
+
     if from_glib(inheritunheritables) {
         dst.clip_path.clone_from(&src.clip_path);
         dst.comp_op.clone_from(&src.comp_op);
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 0c64a29c..86efd373 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -85,9 +85,7 @@ impl NodeTrait for NodeSwitch {
 
         drawing_ctx::push_discrete_layer(draw_ctx, clipping);
 
-        if let Some(child) = node.children()
-            .find(|c| state::get_cond_true(c.get_state()))
-        {
+        if let Some(child) = node.children().find(|c| state::get_cond(c.get_state())) {
             let boxed_child = box_node(child.clone());
 
             drawing_ctx::draw_node_from_stack(draw_ctx, boxed_child, 0, clipping);
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index e0c30d0e..eb1392fe 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -693,7 +693,7 @@ pub extern "C" fn rsvg_node_chars_new(raw_parent: *const RsvgNode) -> *const Rsv
     let node = boxed_node_new(NodeType::Chars, raw_parent, Box::new(NodeChars::new()));
 
     let state = rsvg_node_get_state(node);
-    state::set_cond_true(state, false);
+    state::set_cond(state, false);
 
     node
 }


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