[librsvg/wip/dimensions-api] Abstract the "establish a new viewport" construct from SVG into DrawingCtx



commit 3145105cfd8e19f04b7954000aaf0b8c5c0b5089
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Feb 11 20:26:05 2019 -0600

    Abstract the "establish a new viewport" construct from SVG into DrawingCtx
    
    This commit does three things:
    
    1. Adds AspectRatio::viewport_to_viewbox_transform(), which returns a
       Matrix.
    
    2. Moves most of draw_in_viewport() into a new
       DrawingCtx::push_new_viewport().
    
    3. Leaves draw_in_viewport() as just the thing that checks viewport
       sizes and calls draw_ctx.with_discrete_layer().

 rsvg_internals/src/aspect_ratio.rs | 30 ++++++++++++++++++++++++-
 rsvg_internals/src/drawing_ctx.rs  | 45 ++++++++++++++++++++++++++++++++++++++
 rsvg_internals/src/viewport.rs     | 39 +--------------------------------
 3 files changed, 75 insertions(+), 39 deletions(-)
---
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index 8af83ed3..7c1352b8 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -22,10 +22,11 @@
 
 use std::ops::Deref;
 
-use cairo;
+use cairo::{self, MatrixTrait};
 
 use cssparser::{CowRcStr, Parser};
 use error::ValueErrorKind;
+use float_eq_cairo::ApproxEqCairo;
 use parsers::Parse;
 use parsers::ParseError;
 use viewbox::ViewBox;
@@ -146,6 +147,33 @@ impl AspectRatio {
             }
         }
     }
+
+    // Computes the viewport to viewbox transformation, or returns None
+    // if the vbox has 0 width or height.
+    pub fn viewport_to_viewbox_transform(
+        &self,
+        vbox: Option<ViewBox>,
+        viewport: &cairo::Rectangle,
+    ) -> Option<cairo::Matrix> {
+        if let Some(vbox) = vbox {
+            if vbox.width.approx_eq_cairo(&0.0) || vbox.height.approx_eq_cairo(&0.0) {
+                // Width or height of 0 for the viewBox disables rendering of the element
+                // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+                None
+            } else {
+                let (x, y, w, h) = self.compute(&vbox, viewport);
+                let mut matrix = cairo::Matrix::identity();
+                matrix.translate(x, y);
+                matrix.scale(w / vbox.width, h / vbox.height);
+                matrix.translate(-vbox.x, -vbox.y);
+                Some(matrix)
+            }
+        } else {
+            let mut matrix = cairo::Matrix::identity();
+            matrix.translate(viewport.x, viewport.y);
+            Some(matrix)
+        }
+    }
 }
 
 fn parse_align_xy(ident: &CowRcStr) -> Result<Option<(X, Y)>, ValueErrorKind> {
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 4a4662fb..be7ba65e 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -6,6 +6,7 @@ use std::cell::RefCell;
 use std::rc::{Rc, Weak};
 
 use allowed_url::Fragment;
+use aspect_ratio::AspectRatio;
 use bbox::BoundingBox;
 use clip_path::{ClipPathUnits, NodeClipPath};
 use coord_units::CoordUnits;
@@ -33,6 +34,7 @@ use surface_utils::shared_surface::SharedImageSurface;
 use svg::Svg;
 use unit_interval::UnitInterval;
 use viewbox::ViewBox;
+use viewport::ClipMode;
 
 /// Holds values that are required to normalize `Length` values to a current viewport.
 ///
@@ -225,6 +227,49 @@ impl DrawingCtx {
         }
     }
 
+    pub fn push_new_viewport(
+        &self,
+        vbox: Option<ViewBox>,
+        viewport: &cairo::Rectangle,
+        preserve_aspect_ratio: AspectRatio,
+        clip_mode: Option<ClipMode>,
+    ) -> Option<ViewParams> {
+        if let Some(ref clip) = clip_mode {
+            if *clip == ClipMode::ClipToViewport {
+                self.clip(viewport.x, viewport.y, viewport.width, viewport.height);
+            }
+        }
+
+        if let Some(vbox) = vbox {
+            // the preserveAspectRatio attribute is only used if viewBox is specified
+            // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
+
+            if let Some(matrix) =
+                preserve_aspect_ratio.viewport_to_viewbox_transform(Some(vbox), viewport)
+            {
+                let params = self.push_view_box(vbox.width, vbox.height);
+
+                self.cr.transform(matrix);
+
+                if let Some(ref clip) = clip_mode {
+                    if *clip == ClipMode::ClipToVbox {
+                        self.clip(vbox.x, vbox.y, vbox.width, vbox.height);
+                    }
+                }
+
+                Some(params)
+            } else {
+                // Width or height of 0 for the viewBox disables rendering of the element
+                // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+                return None;
+            }
+        } else {
+            let params = self.push_view_box(viewport.width, viewport.height);
+            self.cr.translate(viewport.x, viewport.y);
+            Some(params)
+        }
+    }
+
     pub fn insert_bbox(&mut self, bbox: &BoundingBox) {
         self.bbox.insert(bbox);
     }
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index 928ab449..679d5e14 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -36,44 +36,7 @@ pub fn draw_in_viewport(
     }
 
     draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
-        let cr = dc.get_cairo_context();
-
-        if let Some(ref clip) = clip_mode {
-            if *clip == ClipMode::ClipToViewport {
-                dc.clip(viewport.x, viewport.y, viewport.width, viewport.height);
-            }
-        }
-
-        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
-
-            if vbox.width.approx_eq_cairo(&0.0) || vbox.height.approx_eq_cairo(&0.0) {
-                // Width or height of 0 for the viewBox disables rendering of the element
-                // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
-                return Ok(());
-            }
-
-            let params = dc.push_view_box(vbox.width, vbox.height);
-
-            let (x, y, w, h) = preserve_aspect_ratio.compute(&vbox, viewport);
-
-            cr.translate(x, y);
-            cr.scale(w / vbox.width, h / vbox.height);
-            cr.translate(-vbox.x, -vbox.y);
-
-            if let Some(ref clip) = clip_mode {
-                if *clip == ClipMode::ClipToVbox {
-                    dc.clip(vbox.x, vbox.y, vbox.width, vbox.height);
-                }
-            }
-
-            params
-        } else {
-            let params = dc.push_view_box(viewport.width, viewport.height);
-            cr.translate(viewport.x, viewport.y);
-            params
-        };
+        let _params = dc.push_new_viewport(vbox, viewport, preserve_aspect_ratio, clip_mode);
 
         let res = draw_fn(dc);
 


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