[librsvg/wip/dimensions-api] image.rs: Use DrawingCtx.push_new_viewport() instead of doing things by hand



commit 7ecf35a35a597b57034cccdfee57fa6d6f3f0caf
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Feb 12 09:34:07 2019 -0600

    image.rs: Use DrawingCtx.push_new_viewport() instead of doing things by hand
    
    Now that function takes care of clipping to the viewport when the
    aspect ratio has "slice".

 rsvg_internals/src/image.rs | 79 ++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 41 deletions(-)
---
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 01fc92b2..bab563d7 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -1,5 +1,5 @@
 use cairo;
-use cairo::{MatrixTrait, PatternTrait, Rectangle};
+use cairo::{PatternTrait, Rectangle};
 use std::cell::{Cell, RefCell};
 
 use allowed_url::Href;
@@ -15,6 +15,7 @@ use parsers::{ParseError, ParseValue};
 use property_bag::PropertyBag;
 use rect::RectangleExt;
 use viewbox::ViewBox;
+use viewport::ClipMode;
 
 pub struct NodeImage {
     aspect: Cell<AspectRatio>,
@@ -101,13 +102,15 @@ impl NodeTrait for NodeImage {
 
             let aspect = self.aspect.get();
 
-            if !values.is_overflow() && aspect.is_slice() {
-                dc.clip(x, y, w, h);
-            }
+            let clip_mode = if !values.is_overflow() && aspect.is_slice() {
+                Some(ClipMode::ClipToViewport)
+            } else {
+                None
+            };
 
-            let width = surface.width();
-            let height = surface.height();
-            if clipping || width == 0 || height == 0 {
+            let image_width = surface.width();
+            let image_height = surface.height();
+            if clipping || image_width == 0 || image_height == 0 {
                 return Ok(());
             }
 
@@ -122,45 +125,39 @@ impl NodeTrait for NodeImage {
                 },
             ));
 
-            let width = f64::from(width);
-            let height = f64::from(height);
-
-            let (x, y, w, h) = aspect.compute(
-                &ViewBox::new(0.0, 0.0, width, height),
-                &Rectangle::new(x, y, w, h),
-            );
-
             let cr = dc.get_cairo_context();
-
             cr.save();
 
-            dc.set_affine_on_cr(&cr);
-            cr.scale(w / width, h / height);
-            let x = x * width / w;
-            let y = y * height / h;
-
-            // We need to set extend appropriately, so can't use cr.set_source_surface().
-            //
-            // If extend is left at its default value (None), then bilinear scaling uses
-            // transparency outside of the image producing incorrect results.
-            // For example, in svg1.1/filters-blend-01-b.svgthere's a completely
-            // opaque 100×1 image of a gradient scaled to 100×98 which ends up
-            // transparent almost everywhere without this fix (which it shouldn't).
-            let ptn = surface.to_cairo_pattern();
-            let mut matrix = cairo::Matrix::identity();
-            matrix.translate(-x, -y);
-            ptn.set_matrix(matrix);
-            ptn.set_extend(cairo::Extend::Pad);
-            cr.set_source(&ptn);
-
-            // Clip is needed due to extend being set to pad.
-            cr.rectangle(x, y, width, height);
-            cr.clip();
-
-            cr.paint();
+            let image_width = f64::from(image_width);
+            let image_height = f64::from(image_height);
 
-            cr.restore();
+            if let Some(_params) = dc.push_new_viewport(
+                Some(ViewBox::new(0.0, 0.0, image_width, image_height)),
+                &Rectangle::new(x, y, w, h),
+                aspect,
+                clip_mode,
+            ) {
+                dc.set_affine_on_cr(&cr);
+
+                // We need to set extend appropriately, so can't use cr.set_source_surface().
+                //
+                // If extend is left at its default value (None), then bilinear scaling uses
+                // transparency outside of the image producing incorrect results.
+                // For example, in svg1.1/filters-blend-01-b.svgthere's a completely
+                // opaque 100×1 image of a gradient scaled to 100×98 which ends up
+                // transparent almost everywhere without this fix (which it shouldn't).
+                let ptn = surface.to_cairo_pattern();
+                ptn.set_extend(cairo::Extend::Pad);
+                cr.set_source(&ptn);
+
+                // Clip is needed due to extend being set to pad.
+                cr.rectangle(0.0, 0.0, image_width, image_height);
+                cr.clip();
+
+                cr.paint();
+            }
 
+            cr.restore();
             dc.insert_bbox(&bbox);
             Ok(())
         })


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