[librsvg: 2/3] (#746) - Possible cairo_save() without cairo_restore() in render_layer()




commit d2aec3d8a04b9f6ee6d02cb7f67d919b44ace2e7
Author: Federico Mena Quintero <federico gnome org>
Date:   Fri Jun 4 13:06:03 2021 -0500

    (#746) - Possible cairo_save() without cairo_restore() in render_layer()
    
    The code has a "?" in the call to get_node_or_root, so it could return
    before doing the cairo_restore().
    
    This is not a problem for rsvg-convert, since it always uses
    render_element when an element id is specified.
    
    It is critical for the C API, where render_cairo_sub/render_layer call
    into Handle.render_layer.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/746

 src/drawing_ctx.rs |  4 ++--
 src/handle.rs      | 12 ++++--------
 2 files changed, 6 insertions(+), 10 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 1d7d8f95..1aead6ad 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -249,10 +249,10 @@ pub fn draw_tree(
 }
 
 /// Does `cairo_save()` on creation, and will `cairo_restore()` on `Drop`.
-struct SavedCr(cairo::Context);
+pub struct SavedCr(cairo::Context);
 
 impl SavedCr {
-    fn new(cr: &cairo::Context) -> SavedCr {
+    pub fn new(cr: &cairo::Context) -> SavedCr {
         cr.save();
         SavedCr(cr.clone())
     }
diff --git a/src/handle.rs b/src/handle.rs
index 9aea4c9f..f8cc9ff6 100644
--- a/src/handle.rs
+++ b/src/handle.rs
@@ -7,7 +7,7 @@ use crate::bbox::BoundingBox;
 use crate::css::{Origin, Stylesheet};
 use crate::document::{AcquiredNodes, Document, NodeId};
 use crate::dpi::Dpi;
-use crate::drawing_ctx::{draw_tree, DrawingMode, ViewParams};
+use crate::drawing_ctx::{draw_tree, DrawingMode, SavedCr, ViewParams};
 use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
 use crate::length::*;
 use crate::node::{CascadedValues, Node, NodeBorrow};
@@ -249,13 +249,13 @@ impl Handle {
     ) -> Result<(), RenderingError> {
         check_cairo_context(cr)?;
 
-        cr.save();
-
         let node = self.get_node_or_root(id)?;
         let root = self.document.root();
 
         let viewport = Rect::from(*viewport);
 
+        let _saved_cr = SavedCr::new(&cr);
+
         let res = draw_tree(
             DrawingMode::LimitToStack { node, root },
             cr,
@@ -267,8 +267,6 @@ impl Handle {
             &mut AcquiredNodes::new(&self.document),
         );
 
-        cr.restore();
-
         res.map(|_bbox| ())
     }
 
@@ -348,7 +346,7 @@ impl Handle {
 
         // Render, transforming so element is at the new viewport's origin
 
-        cr.save();
+        let _saved_cr = SavedCr::new(&cr);
 
         let factor =
             (element_viewport.width / ink_r.width()).min(element_viewport.height / ink_r.height());
@@ -368,8 +366,6 @@ impl Handle {
             &mut AcquiredNodes::new(&self.document),
         );
 
-        cr.restore();
-
         res.map(|_bbox| ())
     }
 


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