Skip to content

Commit

Permalink
Add support for markers in-between fills/strokes.
Browse files Browse the repository at this point in the history
Closes #550
  • Loading branch information
LaurenzV authored Nov 6, 2023
1 parent 23d689d commit 96dd398
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 13 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified crates/resvg/tests/tests/painting/paint-order/stroke-markers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 53 additions & 13 deletions crates/usvg-parser/src/converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::hash::{Hash, Hasher};
use std::rc::Rc;
use std::str::FromStr;

use svgtypes::{Length, LengthUnit as Unit};
use svgtypes::{Length, LengthUnit as Unit, PaintOrderKind};
use usvg_tree::*;

use crate::svgtree::{self, AId, EId, FromValue, SvgNode};
Expand Down Expand Up @@ -665,17 +665,17 @@ fn convert_path(
node.find_attribute(AId::PaintOrder).unwrap_or_default();
let paint_order = svg_paint_order_to_usvg(raw_paint_order);

// If a path doesn't have a fill or a stroke than it's invisible.
// If a path doesn't have a fill or a stroke then it's invisible.
// By setting `visibility` to `hidden` we are disabling rendering of this path.
if fill.is_none() && stroke.is_none() {
visibility = Visibility::Hidden;
}

let mut markers_group = None;
let mut markers_node = None;
if crate::marker::is_valid(node) && visibility == Visibility::Visible {
let mut g = parent.append_kind(NodeKind::Group(Group::default()));
crate::marker::convert(node, &path, state, cache, &mut g);
markers_group = Some(g);
let mut marker = Node::new(NodeKind::Group(Group::default()));
crate::marker::convert(node, &path, state, cache, &mut marker);
markers_node = Some(marker);
}

// Nodes generated by markers must not have an ID. Otherwise we would have duplicates.
Expand All @@ -685,7 +685,7 @@ fn convert_path(
String::new()
};

parent.append_kind(NodeKind::Path(Path {
let path = Path {
id,
visibility,
fill,
Expand All @@ -694,14 +694,54 @@ fn convert_path(
rendering_mode,
text_bbox: None,
data: path,
}));
};

let append_marker = || {
if let Some(markers_node) = markers_node {
parent.append(markers_node);
}
};

let append_path = || {
parent.append(Node::new(NodeKind::Path(path.clone())));
};

if raw_paint_order.order[2] == svgtypes::PaintOrderKind::Markers {
// Insert markers group after `path`.
if let Some(g) = markers_group {
g.detach();
parent.append(g);
match raw_paint_order.order {
[PaintOrderKind::Markers, _, _] => {
append_marker();
append_path();
}
[first, PaintOrderKind::Markers, last] => {
let append_single_paint_path = |paint_order_kind: PaintOrderKind| match paint_order_kind
{
PaintOrderKind::Fill => {
if !path.fill.is_none() {
let mut fill_path = path.clone();
fill_path.stroke = None;
fill_path.id = String::new();
parent.append(Node::new(NodeKind::Path(fill_path)));
}
}
PaintOrderKind::Stroke => {
if !path.stroke.is_none() {
let mut stroke_path = path.clone();
stroke_path.fill = None;
stroke_path.id = String::new();
parent.append(Node::new(NodeKind::Path(stroke_path)));
}
}
_ => {}
};

append_single_paint_path(first);
append_marker();
append_single_paint_path(last)
}
[_, _, PaintOrderKind::Markers] => {
append_path();
append_marker();
}
_ => append_path(),
}
}

Expand Down

0 comments on commit 96dd398

Please sign in to comment.