[librsvg] stop.rs: Start porting the gradient stop element to Rust



commit 6253c01b7693f311fd1283d4a1cd724ba7635c6a
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed May 31 18:28:55 2017 -0500

    stop.rs: Start porting the gradient stop element to Rust

 Makefile.am      |    1 +
 rust/src/lib.rs  |    5 ++
 rust/src/stop.rs |  169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 8ac975f..02620b4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -93,6 +93,7 @@ RUST_SOURCES =                                        \
        rust/src/pt.rs                          \
        rust/src/shapes.rs                      \
        rust/src/state.rs                       \
+       rust/src/stop.rs                        \
        rust/src/structure.rs                   \
        rust/src/transform.rs                   \
        rust/src/util.rs                        \
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index a4093a5..e789e13 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -99,6 +99,10 @@ pub use shapes::{
     rsvg_node_rect_new,
 };
 
+pub use stop::{
+    rsvg_node_stop_new
+};
+
 pub use structure::{
     rsvg_node_group_new,
     rsvg_node_defs_new,
@@ -141,6 +145,7 @@ mod path_parser;
 mod pattern;
 mod property_bag;
 mod state;
+mod stop;
 mod shapes;
 mod structure;
 mod transform;
diff --git a/rust/src/stop.rs b/rust/src/stop.rs
new file mode 100644
index 0000000..d002c52
--- /dev/null
+++ b/rust/src/stop.rs
@@ -0,0 +1,169 @@
+use ::libc;
+use ::cssparser;
+use ::glib::translate::*;
+
+use std::cell::Cell;
+
+use color::*;
+use drawing_ctx;
+use drawing_ctx::*;
+use error::*;
+use handle::RsvgHandle;
+use length::*;
+use node::*;
+use opacity::*;
+use property_bag;
+use property_bag::*;
+use state::RsvgState;
+
+struct NodeStop {
+    offset: Cell<f64>,
+    rgba: Cell<u32>
+}
+
+impl NodeStop {
+    fn new () -> NodeStop {
+        NodeStop {
+            offset: Cell::new (0.0),
+            rgba: Cell::new (0)
+        }
+    }
+}
+
+impl NodeTrait for NodeStop {
+    fn set_atts (&self, node: &RsvgNode, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> 
NodeResult {
+        let offset_length = property_bag::length_or_default (pbag, "offset", LengthDir::Both)?;
+        match offset_length.unit {
+            LengthUnit::Default |
+            LengthUnit::Percent => {
+                let mut offset = offset_length.length;
+
+                if offset < 0.0 {
+                    offset = 0.0;
+                } else if offset > 1.0 {
+                    offset = 1.0;
+                }
+
+                self.offset.set (offset);
+            },
+
+            _ => {
+                return Err (NodeError::value_error ("offset", "stop offset must be in default or percent 
units"));
+            }
+        }
+
+        let state = node.get_state ();
+
+        // FIXME: this is the only place where rsvg_parse_style() and
+        // rsvg_parse_style_pairs() are called outside of the
+        // rsvg-base.c machinery.  That one indirectly calls them via
+        // rsvg_parse_style_attrs().
+        //
+        // Should we resolve the stop-color / stop-opacity at
+        // rendering time?
+
+        if let Some (v) = property_bag::lookup (pbag, "style") {
+            unsafe {
+                rsvg_parse_style (handle, state, v.to_glib_none ().0);
+            }
+        }
+
+        unsafe {
+            rsvg_parse_style_pairs (state, pbag);
+        }
+
+        let inherited_state = drawing_ctx::state_new ();
+        drawing_ctx::state_reconstruct (inherited_state, box_node (node.clone ()));
+
+        let mut color_rgba: cssparser::RGBA;
+
+        let stop_color = drawing_ctx::state_get_stop_color (state)
+            .map_err (|e| NodeError::attribute_error ("stop-color", e))?;
+
+        match stop_color {
+            None => color_rgba = cssparser::RGBA::transparent (),
+
+            Some (Color::Inherit) => {
+                let inherited_stop_color = drawing_ctx::state_get_stop_color (inherited_state)
+                    .map_err (|e| NodeError::attribute_error ("stop-color", e))?;
+
+                match inherited_stop_color {
+                    None => unreachable! (),
+
+                    Some (Color::Inherit) => color_rgba = cssparser::RGBA::transparent (),
+                    Some (Color::CurrentColor) => {
+                        let color = drawing_ctx::state_get_current_color (inherited_state);
+                        match color {
+                            Color::RGBA (rgba) => color_rgba = rgba,
+                            _ => unreachable! ()
+                        }
+                    },
+                    
+                    Some (Color::RGBA (rgba)) => color_rgba = rgba
+                }
+            },
+
+            Some (Color::CurrentColor) => {
+                let color = drawing_ctx::state_get_current_color (inherited_state);
+                match color {
+                    Color::RGBA (rgba) => color_rgba = rgba,
+                    _ => unreachable! ()
+                }
+            }
+
+            Some (Color::RGBA (rgba)) => color_rgba = rgba
+        }
+
+        let stop_opacity = drawing_ctx::state_get_stop_opacity (state)
+            .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;
+
+        match stop_opacity {
+            None => color_rgba.alpha = 0xff,
+
+            Some (Opacity::Inherit) => {
+                let inherited_opacity = drawing_ctx::state_get_stop_opacity (inherited_state)
+                    .map_err (|e| NodeError::attribute_error ("stop-opacity", e))?;
+
+                match inherited_opacity {
+                    Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity),
+                    _ => color_rgba.alpha = 0xff
+                }
+            },
+
+            Some (Opacity::Specified (opacity)) => color_rgba.alpha = opacity_to_u8 (opacity)
+        }
+
+        self.rgba.set (u32_from_rgba (color_rgba));
+
+        drawing_ctx::state_free (inherited_state);
+
+        Ok (())
+    }
+
+    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+        // nothing; paint servers are handled specially
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        unreachable! ();
+    }
+}
+
+fn u32_from_rgba (rgba: cssparser::RGBA) -> u32 {
+    ((rgba.red as u32) << 24) |
+    ((rgba.green as u32) << 16) |
+    ((rgba.blue as u32) << 8) |
+    (rgba.alpha as u32)
+}
+
+extern "C" {
+    fn rsvg_parse_style_pairs (state: *mut RsvgState, pbag: *const RsvgPropertyBag);
+    fn rsvg_parse_style (handle: *const RsvgHandle, state: *mut RsvgState, string: *const libc::c_char);
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_stop_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+    boxed_node_new (NodeType::Stop,
+                    raw_parent,
+                    Box::new (NodeStop::new ()))
+}


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