[librsvg] DrawingCtx::push_view_box(): Return a ViewParams object



commit 36fe10413222b4e2d5163e843c5ec1b8d90507c6
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Sep 4 15:02:08 2018 -0500

    DrawingCtx::push_view_box(): Return a ViewParams object
    
    We will later make this object pop the viewbox when dropped.

 rsvg_internals/src/drawing_ctx.rs     |  4 +-
 rsvg_internals/src/filters/context.rs | 12 +++---
 rsvg_internals/src/gradient.rs        | 62 ++++++++++++++++---------------
 rsvg_internals/src/marker.rs          | 10 ++---
 rsvg_internals/src/mask.rs            | 70 +++++++++++++++++++----------------
 rsvg_internals/src/pattern.rs         | 37 ++++++++++--------
 rsvg_internals/src/viewport.rs        | 11 ++++--
 7 files changed, 114 insertions(+), 92 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 1f9e82c2..c58b9534 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -191,9 +191,11 @@ impl<'a> DrawingCtx<'a> {
         }
     }
 
-    pub fn push_view_box(&mut self, width: f64, height: f64) {
+    pub fn push_view_box(&mut self, width: f64, height: f64) -> ViewParams {
         self.vb_stack.push(self.vb);
         self.vb = ViewBox::new(0.0, 0.0, width, height);
+
+        self.get_view_params()
     }
 
     pub fn pop_view_box(&mut self) {
diff --git a/rsvg_internals/src/filters/context.rs b/rsvg_internals/src/filters/context.rs
index 98c5eb50..1a5aecbc 100644
--- a/rsvg_internals/src/filters/context.rs
+++ b/rsvg_internals/src/filters/context.rs
@@ -125,9 +125,11 @@ fn compute_effects_region(
     // It's done this way because with ObjectBoundingBox, non-percentage values are supposed to
     // represent the fractions of the referenced node, and with width and height = 1, 1 this
     // works out exactly like that.
-    if filter.filterunits.get() == CoordUnits::ObjectBoundingBox {
-        draw_ctx.push_view_box(1.0, 1.0);
-    }
+    let params = if filter.filterunits.get() == CoordUnits::ObjectBoundingBox {
+        draw_ctx.push_view_box(1.0, 1.0)
+    } else {
+        draw_ctx.get_view_params()
+    };
 
     // With filterunits == ObjectBoundingBox, lengths represent fractions or percentages of the
     // referencing node. No units are allowed (it's checked during attribute parsing).
@@ -139,8 +141,6 @@ fn compute_effects_region(
             height: filter.height.get().get_unitless(),
         }
     } else {
-        let params = draw_ctx.get_view_params();
-
         cairo::Rectangle {
             x: filter.x.get().normalize(values, &params),
             y: filter.y.get().normalize(values, &params),
@@ -445,7 +445,7 @@ impl FilterContext {
 
         // See comments in compute_effects_region() for how this works.
         if filter.primitiveunits.get() == CoordUnits::ObjectBoundingBox {
-            draw_ctx.push_view_box(1.0, 1.0);
+            let _params = draw_ctx.push_view_box(1.0, 1.0);
             let rv = f(Box::new(Length::get_unitless));
             draw_ctx.pop_view_box();
 
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index ea1186f6..bcde6f06 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -502,24 +502,26 @@ fn set_linear_gradient_on_pattern(
     if let GradientVariant::Linear { x1, y1, x2, y2 } = gradient.variant {
         let units = gradient.common.units.unwrap();
 
-        if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
-            draw_ctx.push_view_box(1.0, 1.0);
-        }
+        {
+            let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
+                draw_ctx.push_view_box(1.0, 1.0)
+            } else {
+                draw_ctx.get_view_params()
+            };
 
-        let params = draw_ctx.get_view_params();
+            let mut pattern = cairo::LinearGradient::new(
+                x1.as_ref().unwrap().normalize(values, &params),
+                y1.as_ref().unwrap().normalize(values, &params),
+                x2.as_ref().unwrap().normalize(values, &params),
+                y2.as_ref().unwrap().normalize(values, &params),
+            );
 
-        let mut pattern = cairo::LinearGradient::new(
-            x1.as_ref().unwrap().normalize(values, &params),
-            y1.as_ref().unwrap().normalize(values, &params),
-            x2.as_ref().unwrap().normalize(values, &params),
-            y2.as_ref().unwrap().normalize(values, &params),
-        );
+            if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
+                draw_ctx.pop_view_box();
+            }
 
-        if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
-            draw_ctx.pop_view_box();
+            set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
         }
-
-        set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
     } else {
         unreachable!();
     }
@@ -584,27 +586,29 @@ fn set_radial_gradient_on_pattern(
     if let GradientVariant::Radial { cx, cy, r, fx, fy } = gradient.variant {
         let units = gradient.common.units.unwrap();
 
-        if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
-            draw_ctx.push_view_box(1.0, 1.0);
-        }
+        {
+            let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
+                draw_ctx.push_view_box(1.0, 1.0)
+            } else {
+                draw_ctx.get_view_params()
+            };
 
-        let params = draw_ctx.get_view_params();
+            let n_cx = cx.as_ref().unwrap().normalize(values, &params);
+            let n_cy = cy.as_ref().unwrap().normalize(values, &params);
+            let n_r = r.as_ref().unwrap().normalize(values, &params);
+            let n_fx = fx.as_ref().unwrap().normalize(values, &params);
+            let n_fy = fy.as_ref().unwrap().normalize(values, &params);
 
-        let n_cx = cx.as_ref().unwrap().normalize(values, &params);
-        let n_cy = cy.as_ref().unwrap().normalize(values, &params);
-        let n_r = r.as_ref().unwrap().normalize(values, &params);
-        let n_fx = fx.as_ref().unwrap().normalize(values, &params);
-        let n_fy = fy.as_ref().unwrap().normalize(values, &params);
+            let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
 
-        let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
+            let mut pattern = cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r);
 
-        let mut pattern = cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r);
+            if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
+                draw_ctx.pop_view_box();
+            }
 
-        if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
-            draw_ctx.pop_view_box();
+            set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
         }
-
-        set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
     } else {
         unreachable!();
     }
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 47022cf3..fd2269ca 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -159,7 +159,7 @@ impl NodeMarker {
             affine.scale(line_width, line_width);
         }
 
-        if let Some(vbox) = self.vbox.get() {
+        let params = if let Some(vbox) = self.vbox.get() {
             let (_, _, w, h) = self.aspect.get().compute(
                 vbox.0.width,
                 vbox.0.height,
@@ -171,12 +171,10 @@ impl NodeMarker {
 
             affine.scale(w / vbox.0.width, h / vbox.0.height);
 
-            draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
+            draw_ctx.push_view_box(vbox.0.width, vbox.0.height)
         } else {
-            draw_ctx.push_view_box(marker_width, marker_height);
-        }
-
-        let params = draw_ctx.get_view_params();
+            draw_ctx.push_view_box(marker_width, marker_height)
+        };
 
         affine.translate(
             -self.ref_x.get().normalize(&values, &params),
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index f0ede8d1..010e8294 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -83,20 +83,24 @@ impl NodeMask {
         let mask_units = CoordUnits::from(self.units.get());
         let content_units = CoordUnits::from(self.content_units.get());
 
-        if mask_units == CoordUnits::ObjectBoundingBox {
-            draw_ctx.push_view_box(1.0, 1.0);
-        }
+        let (x, y, w, h) = {
+            let params = if mask_units == CoordUnits::ObjectBoundingBox {
+                draw_ctx.push_view_box(1.0, 1.0)
+            } else {
+                draw_ctx.get_view_params()
+            };
 
-        let params = draw_ctx.get_view_params();
+            let x = self.x.get().normalize(&values, &params);
+            let y = self.y.get().normalize(&values, &params);
+            let w = self.width.get().normalize(&values, &params);
+            let h = self.height.get().normalize(&values, &params);
 
-        let x = self.x.get().normalize(&values, &params);
-        let y = self.y.get().normalize(&values, &params);
-        let w = self.width.get().normalize(&values, &params);
-        let h = self.height.get().normalize(&values, &params);
+            if mask_units == CoordUnits::ObjectBoundingBox {
+                draw_ctx.pop_view_box();
+            }
 
-        if mask_units == CoordUnits::ObjectBoundingBox {
-            draw_ctx.pop_view_box();
-        }
+            (x, y, w, h)
+        };
 
         // Use a scope because mask_cr needs to release the
         // reference to the surface before we access the pixels
@@ -130,32 +134,36 @@ impl NodeMask {
                 draw_ctx.clip(x, y, w, h);
             }
 
-            if content_units == CoordUnits::ObjectBoundingBox {
-                let bbtransform = cairo::Matrix::new(
-                    bbox_rect.width,
-                    0.0,
-                    0.0,
-                    bbox_rect.height,
-                    bbox_rect.x,
-                    bbox_rect.y,
-                );
+            {
+                let _params = if content_units == CoordUnits::ObjectBoundingBox {
+                    let bbtransform = cairo::Matrix::new(
+                        bbox_rect.width,
+                        0.0,
+                        0.0,
+                        bbox_rect.height,
+                        bbox_rect.x,
+                        bbox_rect.y,
+                    );
 
-                mask_cr.transform(bbtransform);
+                    mask_cr.transform(bbtransform);
 
-                draw_ctx.push_view_box(1.0, 1.0);
-            }
+                    draw_ctx.push_view_box(1.0, 1.0)
+                } else {
+                    draw_ctx.get_view_params()
+                };
 
-            let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
-                node.draw_children(&cascaded, dc, false)
-            });
+                let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
+                    node.draw_children(&cascaded, dc, false)
+                });
 
-            if content_units == CoordUnits::ObjectBoundingBox {
-                draw_ctx.pop_view_box();
-            }
+                if content_units == CoordUnits::ObjectBoundingBox {
+                    draw_ctx.pop_view_box();
+                }
 
-            draw_ctx.set_cairo_context(&save_cr);
+                draw_ctx.set_cairo_context(&save_cr);
 
-            res
+                res
+            }
         }?;
 
         let opacity = {
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 3c458cfb..4eb79f88 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -268,20 +268,24 @@ fn set_pattern_on_draw_context(
     let vbox = pattern.vbox.unwrap();
     let preserve_aspect_ratio = pattern.preserve_aspect_ratio.unwrap();
 
-    if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
-        draw_ctx.push_view_box(1.0, 1.0);
-    }
+    let (pattern_x, pattern_y, pattern_width, pattern_height) = {
+        let params = if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
+            draw_ctx.push_view_box(1.0, 1.0)
+        } else {
+            draw_ctx.get_view_params()
+        };
 
-    let params = draw_ctx.get_view_params();
+        let pattern_x = pattern.x.unwrap().normalize(values, &params);
+        let pattern_y = pattern.y.unwrap().normalize(values, &params);
+        let pattern_width = pattern.width.unwrap().normalize(values, &params);
+        let pattern_height = pattern.height.unwrap().normalize(values, &params);
 
-    let pattern_x = pattern.x.unwrap().normalize(values, &params);
-    let pattern_y = pattern.y.unwrap().normalize(values, &params);
-    let pattern_width = pattern.width.unwrap().normalize(values, &params);
-    let pattern_height = pattern.height.unwrap().normalize(values, &params);
+        if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
+            draw_ctx.pop_view_box();
+        }
 
-    if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
-        draw_ctx.pop_view_box();
-    }
+        (pattern_x, pattern_y, pattern_width, pattern_height)
+    };
 
     // Work out the size of the rectangle so it takes into account the object bounding box
 
@@ -346,7 +350,7 @@ fn set_pattern_on_draw_context(
     let pushed_view_box: bool;
 
     // Create the pattern contents coordinate system
-    if let Some(vbox) = vbox {
+    let _params = if let Some(vbox) = vbox {
         // If there is a vbox, use that
         let (mut x, mut y, w, h) = preserve_aspect_ratio.compute(
             vbox.0.width,
@@ -362,8 +366,9 @@ fn set_pattern_on_draw_context(
 
         caffine = cairo::Matrix::new(w / vbox.0.width, 0.0, 0.0, h / vbox.0.height, x, y);
 
-        draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
+        let params = draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
         pushed_view_box = true;
+        params
     } else if content_units == PatternContentUnits(CoordUnits::ObjectBoundingBox) {
         // If coords are in terms of the bounding box, use them
         let bbrect = bbox.rect.unwrap();
@@ -371,12 +376,14 @@ fn set_pattern_on_draw_context(
         caffine = cairo::Matrix::identity();
         caffine.scale(bbrect.width, bbrect.height);
 
-        draw_ctx.push_view_box(1.0, 1.0);
+        let params = draw_ctx.push_view_box(1.0, 1.0);
         pushed_view_box = true;
+        params
     } else {
         caffine = cairo::Matrix::identity();
         pushed_view_box = false;
-    }
+        draw_ctx.get_view_params()
+    };
 
     if !scwscale.approx_eq_cairo(&1.0) || !schscale.approx_eq_cairo(&1.0) {
         let mut scalematrix = cairo::Matrix::identity();
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index 0c1857d9..7c3a762b 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -47,7 +47,7 @@ pub fn draw_in_viewport(
             dc.clip(vx, vy, vw, vh);
         }
 
-        if let Some(vbox) = vbox {
+        let _params = if let Some(vbox) = vbox {
             // the preserveAspectRatio attribute is only used if viewBox is specified
             // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
 
@@ -57,7 +57,7 @@ pub fn draw_in_viewport(
                 return Ok(());
             }
 
-            dc.push_view_box(vbox.0.width, vbox.0.height);
+            let params = dc.push_view_box(vbox.0.width, vbox.0.height);
 
             let (x, y, w, h) =
                 preserve_aspect_ratio.compute(vbox.0.width, vbox.0.height, vx, vy, vw, vh);
@@ -71,11 +71,14 @@ pub fn draw_in_viewport(
             if do_clip && clip_mode == ClipMode::ClipToVbox {
                 dc.clip(vbox.0.x, vbox.0.y, vbox.0.width, vbox.0.height);
             }
+
+            params
         } else {
-            dc.push_view_box(vw, vh);
+            let params = dc.push_view_box(vw, vh);
             affine.translate(vx, vy);
             dc.get_cairo_context().set_matrix(affine);
-        }
+            params
+        };
 
         let res = draw_fn(dc);
 


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