[librsvg: 1/4] Use Arc<PaintSource> everywhere to avoid copies for context-stroke/context-fill
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/4] Use Arc<PaintSource> everywhere to avoid copies for context-stroke/context-fill
- Date: Thu, 22 Sep 2022 17:19:49 +0000 (UTC)
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]