[librsvg] viewport.rs: new draw_in_viewport() function



commit 2a66e60257225b6d784431097d4aba47df7af9f8
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Sep 27 08:44:40 2017 -0500

    viewport.rs: new draw_in_viewport() function
    
    The general "establish a new viewport" pattern is done in different
    ways in several places in the code.  We capture this pattern in a
    single function which takes care of setting up a clipping rectangle
    and a transformation matrix, and call a lambda to actually draw the
    contents.

 Makefile.am           |    3 +-
 rust/src/lib.rs       |    1 +
 rust/src/structure.rs |   68 +++++++++++--------------------------------------
 rust/src/viewport.rs  |   60 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 54 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ae3f1c9..b18babc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -96,7 +96,8 @@ RUST_SOURCES =                                        \
        rust/src/structure.rs                   \
        rust/src/transform.rs                   \
        rust/src/util.rs                        \
-       rust/src/viewbox.rs
+       rust/src/viewbox.rs                     \
+       rust/src/viewport.rs
 
 RUST_EXTRA =                                   \
        rust/Cargo.lock                         \
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 2533e22..9dd7cec 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -155,3 +155,4 @@ mod structure;
 mod transform;
 mod util;
 mod viewbox;
+mod viewport;
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index abe4ecf..c52ff75 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -18,6 +18,7 @@ use property_bag;
 use property_bag::*;
 use util::*;
 use viewbox::*;
+use viewport::draw_in_viewport;
 
 /***** NodeGroup *****/
 
@@ -171,60 +172,21 @@ impl NodeTrait for NodeSvg {
         let nw = self.w.get ().normalize (draw_ctx);
         let nh = self.h.get ().normalize (draw_ctx);
 
-        // width or height set to 0 disables rendering of the element
-        // https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
-        if double_equals (nw, 0.0) || double_equals (nh, 0.0) {
-            return;
-        }
-
-        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);
-
         let state = drawing_ctx::get_current_state (draw_ctx);
-
-        let affine_old = drawing_ctx::get_current_state_affine (draw_ctx);
-
-        if let Some (vbox) = self.vbox.get () {
-            // viewBox width==0 or height==0 disables rendering of the element
-            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
-            if double_equals (vbox.0.width, 0.0) || double_equals (vbox.0.height, 0.0) {
-                return;
-            }
-
-            let (x, y, w, h) = self.preserve_aspect_ratio.get ().compute (vbox.0.width, vbox.0.height,
-                                                                          nx, ny, nw, nh);
-
-            let mut affine = affine_old;
-            affine.translate (x, y);
-            affine.scale (w / vbox.0.width, h / vbox.0.height);
-            affine.translate (-vbox.0.x, -vbox.0.y);
-            drawing_ctx::set_current_state_affine (draw_ctx, affine);
-
-            drawing_ctx::push_view_box (draw_ctx, vbox.0.width, vbox.0.height);
-        } else {
-            let mut affine = affine_old;
-            affine.translate (nx, ny);
-
-            drawing_ctx::set_current_state_affine (draw_ctx, affine);
-            drawing_ctx::push_view_box (draw_ctx, nw, nh);
-        }
-
-        let affine_new = drawing_ctx::get_current_state_affine (draw_ctx);
-
-        drawing_ctx::push_discrete_layer (draw_ctx);
-
-        // Bounding box addition must be AFTER the discrete layer
-        // push, which must be AFTER the transformation happens.
-
-        if !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some () {
-            drawing_ctx::set_current_state_affine (draw_ctx, affine_old);
-            drawing_ctx::add_clipping_rect (draw_ctx, nx, ny, nw, nh);
-            drawing_ctx::set_current_state_affine (draw_ctx, affine_new);
-        }
-
-        node.draw_children (draw_ctx, -1); // dominate==-1 so it won't reinherit or push a layer
-
-        drawing_ctx::pop_discrete_layer (draw_ctx);
-        drawing_ctx::pop_view_box (draw_ctx);
+        let do_clip = !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some ();
+
+        draw_in_viewport(nx, ny, nw, nh,
+                         do_clip,
+                         self.vbox.get(),
+                         self.preserve_aspect_ratio.get(),
+                         drawing_ctx::get_current_state_affine(draw_ctx),
+                         draw_ctx,
+                         |affine| {
+                             drawing_ctx::state_push(draw_ctx);
+                             drawing_ctx::set_current_state_affine(draw_ctx, affine);
+                             node.draw_children(draw_ctx, -1); // dominate==-1 so it won't reinherit or push 
a layer
+                             drawing_ctx::state_pop(draw_ctx);
+                         });
     }
 
     fn get_c_impl (&self) -> *const RsvgCNodeImpl {
diff --git a/rust/src/viewport.rs b/rust/src/viewport.rs
new file mode 100644
index 0000000..f05caa7
--- /dev/null
+++ b/rust/src/viewport.rs
@@ -0,0 +1,60 @@
+use cairo;
+use cairo::MatrixTrait;
+
+use aspect_ratio::AspectRatio;
+use drawing_ctx;
+use drawing_ctx::RsvgDrawingCtx;
+use util::*;
+use viewbox::*;
+
+pub fn draw_in_viewport<F>(vx: f64, vy: f64, vw: f64, vh: f64,
+                           do_clip: bool,
+                           vbox: Option<ViewBox>,
+                           preserve_aspect_ratio: AspectRatio,
+                           mut affine: cairo::Matrix,
+                           draw_ctx: *const RsvgDrawingCtx,
+                           draw_fn: F)
+    where F: FnOnce(cairo::Matrix)
+{
+    // width or height set to 0 disables rendering of the element
+    // https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
+    // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
+    // https://www.w3.org/TR/SVG/struct.html#ImageElementWidthAttribute
+    // https://www.w3.org/TR/SVG/painting.html#MarkerWidthAttribute
+    
+    if double_equals(vw, 0.0) || double_equals(vh, 0.0) {
+        return;
+    }
+
+    let vbox_size;
+
+    if let Some(vbox) = vbox {
+        // the preserveAspectRatio attribute is only used if viewBox is specified
+        // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
+
+        let (x, y, w, h) = preserve_aspect_ratio.compute(vbox.0.width, vbox.0.height,
+                                                         vx, vy, vw, vh);
+
+        affine.translate(x, y);
+        affine.scale(w / vbox.0.width, h / vbox.0.height);
+        affine.translate(-vbox.0.x, -vbox.0.y);
+
+        vbox_size = (vbox.0.width, vbox.0.height);
+    } else {
+        affine.translate(vx, vy);
+        vbox_size = (vw, vh);
+    }
+
+    drawing_ctx::push_view_box(draw_ctx, vbox_size.0, vbox_size.1);
+    drawing_ctx::push_discrete_layer(draw_ctx);
+
+    if do_clip {
+        drawing_ctx::add_clipping_rect(draw_ctx, vx, vy, vw, vh);
+    }
+
+    draw_fn(affine);
+
+    drawing_ctx::pop_discrete_layer(draw_ctx);
+    drawing_ctx::pop_view_box(draw_ctx);
+    
+}


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