[librsvg: 1/4] Use Arc<PaintSource> everywhere to avoid copies for context-stroke/context-fill




commit 47bfa2551f3238bcef73e156fc0de84de0bce39c
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Sep 21 16:25:22 2022 -0500

    Use Arc<PaintSource> everywhere to avoid copies for context-stroke/context-fill
    
    Once a PaintServer is resolved into a PaintSource, that paint source
    may be used in multiple places:
    
    * The actual stroke/fill of a shape.
    * The context-stroke/context-fill of a shape's markers.
    * The context-stroke/context-fill of a <use>'s children.
    
    We were doing clone() everywhere; now we use an Arc<PaintSource>
    instead to avoid copies.
    
    Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/750>

 src/drawing_ctx.rs  |  5 +++--
 src/layout.rs       | 11 ++++++-----
 src/node.rs         |  9 +++++----
 src/paint_server.rs | 47 ++++++++++++++++++++++++++++++-----------------
 src/text.rs         |  5 +++--
 5 files changed, 47 insertions(+), 30 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 5cbb0a427..6eb200b39 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -12,6 +12,7 @@ use std::cell::RefCell;
 use std::convert::TryFrom;
 use std::f64::consts::*;
 use std::rc::{Rc, Weak};
+use std::sync::Arc;
 
 use crate::accept_language::UserLanguage;
 use crate::aspect_ratio::AspectRatio;
@@ -1631,8 +1632,8 @@ impl DrawingCtx {
         use_rect: Rect,
         link: &NodeId,
         clipping: bool,
-        fill_paint: PaintSource,
-        stroke_paint: PaintSource,
+        fill_paint: Arc<PaintSource>,
+        stroke_paint: Arc<PaintSource>,
     ) -> Result<BoundingBox, RenderingError> {
         // <use> is an element that is used directly, unlike
         // <pattern>, which is used through a fill="url(#...)"
diff --git a/src/layout.rs b/src/layout.rs
index c82b47f90..be858196a 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -3,6 +3,7 @@
 //! The idea is to take the DOM tree and produce a layout tree with SVG concepts.
 
 use std::rc::Rc;
+use std::sync::Arc;
 
 use crate::aspect_ratio::AspectRatio;
 use crate::bbox::BoundingBox;
@@ -76,8 +77,8 @@ pub struct Shape {
     pub is_visible: bool,
     pub paint_order: PaintOrder,
     pub stroke: Stroke,
-    pub stroke_paint: PaintSource,
-    pub fill_paint: PaintSource,
+    pub stroke_paint: Arc<PaintSource>,
+    pub fill_paint: Arc<PaintSource>,
     pub fill_rule: FillRule,
     pub clip_rule: ClipRule,
     pub shape_rendering: ShapeRendering,
@@ -88,8 +89,8 @@ pub struct Shape {
 
 pub struct Marker {
     pub node_ref: Option<Node>,
-    pub context_stroke: PaintSource,
-    pub context_fill: PaintSource,
+    pub context_stroke: Arc<PaintSource>,
+    pub context_fill: Arc<PaintSource>,
 }
 
 /// Image in user-space coordinates.
@@ -112,7 +113,7 @@ pub struct TextSpan {
     pub paint_order: PaintOrder,
     pub stroke: Stroke,
     pub stroke_paint: UserSpacePaintSource,
-    pub stroke_paint_source: PaintSource,
+    pub stroke_paint_source: Arc<PaintSource>,
     pub fill_paint: UserSpacePaintSource,
     pub text_rendering: TextRendering,
     pub link_target: Option<String>,
diff --git a/src/node.rs b/src/node.rs
index 92341765f..69861258d 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -10,6 +10,7 @@
 use markup5ever::QualName;
 use std::cell::{Ref, RefMut};
 use std::fmt;
+use std::sync::Arc;
 
 use crate::bbox::BoundingBox;
 use crate::document::AcquiredNodes;
@@ -102,8 +103,8 @@ impl fmt::Display for NodeData {
 /// `&ComputedValues` whose fields you can access.
 pub struct CascadedValues<'a> {
     inner: CascadedInner<'a>,
-    pub context_stroke: Option<PaintSource>,
-    pub context_fill: Option<PaintSource>,
+    pub context_stroke: Option<Arc<PaintSource>>,
+    pub context_fill: Option<Arc<PaintSource>>,
 }
 
 enum CascadedInner<'a> {
@@ -155,8 +156,8 @@ impl<'a> CascadedValues<'a> {
     pub fn new_from_values(
         node: &'a Node,
         values: &ComputedValues,
-        fill: Option<PaintSource>,
-        stroke: Option<PaintSource>,
+        fill: Option<Arc<PaintSource>>,
+        stroke: Option<Arc<PaintSource>>,
     ) -> CascadedValues<'a> {
         let mut v = Box::new(values.clone());
         node.borrow_element()
diff --git a/src/paint_server.rs b/src/paint_server.rs
index 57d4af468..2395aee98 100644
--- a/src/paint_server.rs
+++ b/src/paint_server.rs
@@ -1,5 +1,7 @@
 //! SVG paint servers.
 
+use std::sync::Arc;
+
 use cssparser::Parser;
 
 use crate::bbox::BoundingBox;
@@ -120,15 +122,20 @@ impl PaintServer {
     /// the paint server is for the `stroke` or `fill` properties.
     ///
     /// `current_color` should be the value of `ComputedValues.color()`.
+    ///
+    /// After a paint server is resolved, the resulting [`PaintSource`] can be used in
+    /// many places: for an actual shape, or for the `context-fill` of a marker for that
+    /// shape.  Therefore, this returns an [`Arc`] so that the `PaintSource` may be shared
+    /// easily.
     pub fn resolve(
         &self,
         acquired_nodes: &mut AcquiredNodes<'_>,
         opacity: UnitInterval,
         current_color: cssparser::RGBA,
-        context_fill: Option<PaintSource>,
-        context_stroke: Option<PaintSource>,
+        context_fill: Option<Arc<PaintSource>>,
+        context_stroke: Option<Arc<PaintSource>>,
         session: &Session,
-    ) -> PaintSource {
+    ) -> Arc<PaintSource> {
         match self {
             PaintServer::Iri {
                 ref iri,
@@ -142,26 +149,26 @@ impl PaintServer {
                     match *node.borrow_element() {
                         Element::LinearGradient(ref g) => {
                             g.resolve(node, acquired_nodes, opacity, session).map(|g| {
-                                PaintSource::Gradient(
+                                Arc::new(PaintSource::Gradient(
                                     g,
                                     alternate.map(|c| resolve_color(&c, opacity, current_color)),
-                                )
+                                ))
                             })
                         }
                         Element::Pattern(ref p) => {
                             p.resolve(node, acquired_nodes, opacity, session).map(|p| {
-                                PaintSource::Pattern(
+                                Arc::new(PaintSource::Pattern(
                                     p,
                                     alternate.map(|c| resolve_color(&c, opacity, current_color)),
-                                )
+                                ))
                             })
                         }
                         Element::RadialGradient(ref g) => {
                             g.resolve(node, acquired_nodes, opacity, session).map(|g| {
-                                PaintSource::Gradient(
+                                Arc::new(PaintSource::Gradient(
                                     g,
                                     alternate.map(|c| resolve_color(&c, opacity, current_color)),
-                                )
+                                ))
                             })
                         }
                         _ => Err(AcquireError::InvalidLinkType(iri.as_ref().clone())),
@@ -187,7 +194,11 @@ impl PaintServer {
                             iri
                         );
 
-                        PaintSource::SolidColor(resolve_color(color, opacity, current_color))
+                        Arc::new(PaintSource::SolidColor(resolve_color(
+                            color,
+                            opacity,
+                            current_color,
+                        )))
                     }
 
                     None => {
@@ -197,19 +208,21 @@ impl PaintServer {
                             iri
                         );
 
-                        PaintSource::None
+                        Arc::new(PaintSource::None)
                     }
                 }),
 
-            PaintServer::SolidColor(color) => {
-                PaintSource::SolidColor(resolve_color(color, opacity, current_color))
-            }
+            PaintServer::SolidColor(color) => Arc::new(PaintSource::SolidColor(resolve_color(
+                color,
+                opacity,
+                current_color,
+            ))),
 
             PaintServer::ContextFill => {
                 if let Some(paint) = context_fill {
                     paint
                 } else {
-                    PaintSource::None
+                    Arc::new(PaintSource::None)
                 }
             }
 
@@ -217,11 +230,11 @@ impl PaintServer {
                 if let Some(paint) = context_stroke {
                     paint
                 } else {
-                    PaintSource::None
+                    Arc::new(PaintSource::None)
                 }
             }
 
-            PaintServer::None => PaintSource::None,
+            PaintServer::None => Arc::new(PaintSource::None),
         }
     }
 }
diff --git a/src/text.rs b/src/text.rs
index 478672878..430ffcc03 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -5,6 +5,7 @@ use pango::IsAttribute;
 use std::cell::RefCell;
 use std::convert::TryFrom;
 use std::rc::Rc;
+use std::sync::Arc;
 
 use crate::bbox::BoundingBox;
 use crate::document::{AcquiredNodes, NodeId};
@@ -120,8 +121,8 @@ struct LayoutSpan {
     y: f64,
     paint_order: PaintOrder,
     stroke: Stroke,
-    stroke_paint: PaintSource,
-    fill_paint: PaintSource,
+    stroke_paint: Arc<PaintSource>,
+    fill_paint: Arc<PaintSource>,
     text_rendering: TextRendering,
     link_target: Option<String>,
     values: Rc<ComputedValues>,


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