[librsvg: 1/2] Implement vector-effect="non-scaling-stroke"
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/2] Implement vector-effect="non-scaling-stroke"
- Date: Tue, 6 Sep 2022 01:13:18 +0000 (UTC)
commit fe5ddfab380530536f61720af79f47ab06106b08
Author: Michael Howell <michael notriddle com>
Date: Sat Sep 3 14:30:10 2022 -0700
Implement vector-effect="non-scaling-stroke"
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/740>
src/drawing_ctx.rs | 40 +++++++++++++++++++---
src/layout.rs | 6 +++-
src/properties.rs | 3 +-
src/property_defs.rs | 14 ++++++++
.../885-vector-effect-non-scaling-stroke-ref.svg | 4 +++
.../885-vector-effect-non-scaling-stroke.svg | 4 +++
tests/src/reference.rs | 6 ++++
7 files changed, 71 insertions(+), 6 deletions(-)
---
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index e7f0b3bfa..5cbb0a427 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -1275,7 +1275,12 @@ impl DrawingCtx {
cr.set_fill_rule(cairo::FillRule::from(shape.fill_rule));
path_helper.set()?;
- let bbox = compute_stroke_and_fill_box(&cr, &shape.stroke, &shape.stroke_paint)?;
+ let bbox = compute_stroke_and_fill_box(
+ &cr,
+ &shape.stroke,
+ &shape.stroke_paint,
+ &dc.initial_viewport,
+ )?;
let stroke_paint = shape.stroke_paint.to_user_space(&bbox, view_params, values);
let fill_paint = shape.fill_paint.to_user_space(&bbox, view_params, values);
@@ -1292,7 +1297,17 @@ impl DrawingCtx {
PaintTarget::Stroke => {
path_helper.set()?;
+ let backup_matrix = if shape.stroke.non_scaling {
+ let matrix = cr.matrix();
+ cr.set_matrix(dc.initial_viewport.transform.into());
+ Some(matrix)
+ } else {
+ None
+ };
dc.stroke(&cr, an, &stroke_paint)?;
+ if let Some(matrix) = backup_matrix {
+ cr.set_matrix(matrix);
+ }
}
PaintTarget::Markers => {
@@ -1420,8 +1435,12 @@ impl DrawingCtx {
}
path.to_cairo(&self.cr, false)?;
- let bbox =
- compute_stroke_and_fill_box(&self.cr, &span.stroke, &span.stroke_paint_source)?;
+ let bbox = compute_stroke_and_fill_box(
+ &self.cr,
+ &span.stroke,
+ &span.stroke_paint_source,
+ &self.initial_viewport,
+ )?;
self.cr.new_path();
if span.is_visible {
@@ -1968,6 +1987,7 @@ fn compute_stroke_and_fill_extents(
cr: &cairo::Context,
stroke: &Stroke,
stroke_paint_source: &PaintSource,
+ initial_viewport: &Viewport,
) -> Result<PathExtents, RenderingError> {
// Dropping the precision of cairo's bezier subdivision, yielding 2x
// _rendering_ time speedups, are these rather expensive operations
@@ -2000,7 +2020,17 @@ fn compute_stroke_and_fill_extents(
let stroke_extents = if !stroke.width.approx_eq_cairo(0.0)
&& !matches!(stroke_paint_source, PaintSource::None)
{
+ let backup_matrix = if stroke.non_scaling {
+ let matrix = cr.matrix();
+ cr.set_matrix(initial_viewport.transform.into());
+ Some(matrix)
+ } else {
+ None
+ };
let (x0, y0, x1, y1) = cr.stroke_extents()?;
+ if let Some(matrix) = backup_matrix {
+ cr.set_matrix(matrix);
+ }
Some(Rect::new(x0, y0, x1, y1))
} else {
None
@@ -2026,8 +2056,10 @@ fn compute_stroke_and_fill_box(
cr: &cairo::Context,
stroke: &Stroke,
stroke_paint_source: &PaintSource,
+ initial_viewport: &Viewport,
) -> Result<BoundingBox, RenderingError> {
- let extents = compute_stroke_and_fill_extents(cr, stroke, stroke_paint_source)?;
+ let extents =
+ compute_stroke_and_fill_extents(cr, stroke, stroke_paint_source, initial_viewport)?;
let ink_rect = match (extents.fill, extents.stroke) {
(None, None) => None,
diff --git a/src/layout.rs b/src/layout.rs
index 4be72eb82..c82b47f90 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -18,7 +18,7 @@ use crate::properties::{
ClipRule, ComputedValues, Direction, FillRule, Filter, FontFamily, FontStretch, FontStyle,
FontVariant, FontWeight, Isolation, MixBlendMode, Opacity, Overflow, PaintOrder,
ShapeRendering, StrokeDasharray, StrokeLinecap, StrokeLinejoin, StrokeMiterlimit,
- TextDecoration, TextRendering, UnicodeBidi, XmlLang,
+ TextDecoration, TextRendering, UnicodeBidi, VectorEffect, XmlLang,
};
use crate::rect::Rect;
use crate::session::Session;
@@ -62,6 +62,8 @@ pub struct Stroke {
pub line_join: StrokeLinejoin,
pub dash_offset: f64,
pub dashes: Box<[f64]>,
+ // https://svgwg.org/svg2-draft/painting.html#non-scaling-stroke
+ pub non_scaling: bool,
}
/// Paths and basic shapes resolved to a path.
@@ -251,6 +253,7 @@ impl Stroke {
let line_cap = values.stroke_line_cap();
let line_join = values.stroke_line_join();
let dash_offset = values.stroke_dashoffset().0.to_user(params);
+ let non_scaling = values.vector_effect() == VectorEffect::NonScalingStroke;
let dashes = match values.stroke_dasharray() {
StrokeDasharray(Dasharray::None) => Box::new([]),
@@ -267,6 +270,7 @@ impl Stroke {
line_join,
dash_offset,
dashes,
+ non_scaling,
}
}
}
diff --git a/src/properties.rs b/src/properties.rs
index 7c6c95a43..810b1ec7b 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -484,7 +484,6 @@ make_properties! {
// "transform-box" => (PresentationAttr::Yes, unimplemented),
// "transform-origin" => (PresentationAttr::Yes, unimplemented),
"unicode-bidi" => (PresentationAttr::Yes, unicode_bidi : UnicodeBidi),
- // "vector-effect" => (PresentationAttr::Yes, unimplemented),
"visibility" => (PresentationAttr::Yes, visibility : Visibility),
// "white-space" => (PresentationAttr::Yes, unimplemented),
// "word-spacing" => (PresentationAttr::Yes, unimplemented),
@@ -501,6 +500,7 @@ make_properties! {
"mix-blend-mode" => (PresentationAttr::No, mix_blend_mode : MixBlendMode),
"paint-order" => (PresentationAttr::Yes, paint_order : PaintOrder),
"text-orientation" => (PresentationAttr::No, text_orientation :
TextOrientation),
+ "vector-effect" => (PresentationAttr::Yes, vector_effect : VectorEffect),
}
// These are not properties, but presentation attributes. However,
@@ -750,6 +750,7 @@ impl SpecifiedValues {
compute!(TextRendering, text_rendering);
compute!(TransformProperty, transform_property);
compute!(UnicodeBidi, unicode_bidi);
+ compute!(VectorEffect, vector_effect);
compute!(Visibility, visibility);
compute!(Width, width);
compute!(WritingMode, writing_mode);
diff --git a/src/property_defs.rs b/src/property_defs.rs
index 435e14127..0018bab2c 100644
--- a/src/property_defs.rs
+++ b/src/property_defs.rs
@@ -1153,6 +1153,20 @@ make_property!(
"plaintext" => Plaintext,
);
+make_property!(
+ /// `vector-effect` property.
+ ///
+ /// SVG2: <https://svgwg.org/svg2-draft/coords.html#VectorEffectProperty>
+ VectorEffect,
+ default: None,
+ inherits_automatically: false,
+
+ identifiers:
+ "none" => None,
+ "non-scaling-stroke" => NonScalingStroke,
+ // non-scaling-size, non-rotation, fixed-position not implemented
+);
+
make_property!(
/// `visibility` property.
///
diff --git a/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke-ref.svg
b/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke-ref.svg
new file mode 100644
index 000000000..5fba0ad31
--- /dev/null
+++ b/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke-ref.svg
@@ -0,0 +1,4 @@
+<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">
+ <rect fill="none" stroke="green" stroke-width="25" width="100%" height="100%"/>
+ <rect x="0" y="25%" width="100%" height="50%" fill="red" stroke-width="25" stroke="blue"/>
+</svg>
diff --git a/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke.svg
b/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke.svg
new file mode 100644
index 000000000..be3937036
--- /dev/null
+++ b/tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke.svg
@@ -0,0 +1,4 @@
+<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg">
+ <rect fill="none" stroke="green" stroke-width="25" width="100%" height="100%"/>
+ <rect x="0" y="250%" width="100%" height="500%" transform="scale(1 0.1)" fill="red"
vector-effect="non-scaling-stroke" stroke-width="25" stroke="blue"/>
+</svg>
diff --git a/tests/src/reference.rs b/tests/src/reference.rs
index a00cb0cef..2234e130a 100644
--- a/tests/src/reference.rs
+++ b/tests/src/reference.rs
@@ -418,3 +418,9 @@ test_svg_reference!(
"tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height.svg",
"tests/fixtures/reftests/bugs-reftests/875-svg-use-width-height-ref.svg"
);
+
+test_svg_reference!(
+ bug_885_vector_effect_non_scaling_stroke,
+ "tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke.svg",
+ "tests/fixtures/reftests/bugs-reftests/885-vector-effect-non-scaling-stroke-ref.svg"
+);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]