Merge pull request #1426 from storytold/q/1410-ai-compound-paint
Fix #1410: an .ai compound path takes its last path's paint, and paths grouped in it stay its paths
This commit is contained in:
commit
487cc29b57
|
|
@ -702,13 +702,17 @@ impl<'a> Reader<'a> {
|
||||||
"*U" => self.close(what, |k| matches!(k, Kind::Compound))?,
|
"*U" => self.close(what, |k| matches!(k, Kind::Compound))?,
|
||||||
_ => self.close(what, |k| matches!(k, Kind::Clip))?,
|
_ => self.close(what, |k| matches!(k, Kind::Clip))?,
|
||||||
};
|
};
|
||||||
let Frame { kind, children: mut kids, gs, clips, hidden: opened_hidden, .. } = f;
|
let Frame { kind, children: kids, gs, clips, hidden: opened_hidden, .. } = f;
|
||||||
// A compound path of clipping paths clips its clipping group.
|
// A compound path of clipping paths clips its clipping group.
|
||||||
let clipping = matches!(kind, Kind::Compound) && !clips.is_empty();
|
let clipping = matches!(kind, Kind::Compound) && !clips.is_empty();
|
||||||
let node = match kind {
|
let node = match kind {
|
||||||
Kind::Compound => {
|
Kind::Compound => {
|
||||||
let Some(first) = kids.first() else { return Ok(()) };
|
// A group in a compound path (`*u u … U *U`) only holds its paths.
|
||||||
let (appearance, opacity, blend, rule) = (first.appearance.clone(), first.opacity, first.blend, path_rule(first));
|
let mut kids = ungrouped(kids);
|
||||||
|
// The compound path's paint is its last path's (a gradient's instance wraps only
|
||||||
|
// that one); the last painted one, should the last have none.
|
||||||
|
let Some(shown) = kids.iter().rev().find(|k| !k.appearance.items.is_empty()).or(kids.last()) else { return Ok(()) };
|
||||||
|
let (appearance, opacity, blend, rule) = (shown.appearance.clone(), shown.opacity, shown.blend, path_rule(shown));
|
||||||
for k in &mut kids {
|
for k in &mut kids {
|
||||||
k.opacity = 1.0;
|
k.opacity = 1.0;
|
||||||
k.blend = BlendMode::Normal;
|
k.blend = BlendMode::Normal;
|
||||||
|
|
@ -1716,6 +1720,18 @@ fn close(bp: &mut BezPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The fill rule of a path or compound node.
|
/// The fill rule of a path or compound node.
|
||||||
|
/// `kids` with the members of each plain group among them in the group's place, at any depth.
|
||||||
|
fn ungrouped(kids: Vec<Node>) -> Vec<Node> {
|
||||||
|
let mut out = Vec::with_capacity(kids.len());
|
||||||
|
for k in kids {
|
||||||
|
match k.kind {
|
||||||
|
NodeKind::Group { children, clip: false } => out.extend(ungrouped(children.into_iter().map(Arc::unwrap_or_clone).collect())),
|
||||||
|
_ => out.push(k),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
fn path_rule(n: &Node) -> FillRule {
|
fn path_rule(n: &Node) -> FillRule {
|
||||||
match &n.kind {
|
match &n.kind {
|
||||||
NodeKind::Path { rule, .. } | NodeKind::Compound { rule, .. } => *rule,
|
NodeKind::Path { rule, .. } | NodeKind::Compound { rule, .. } => *rule,
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,25 @@ fn compound_paths_and_clipping() {
|
||||||
assert!(*clip && matches!(children[0].kind, NodeKind::Path { clipping: true, .. }));
|
assert!(*clip && matches!(children[0].kind, NodeKind::Path { clipping: true, .. }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// #1410: a compound path shows its last path's paint, and paths grouped in it stay its paths.
|
||||||
|
#[test]
|
||||||
|
fn compound_path_takes_its_last_paths_paint() {
|
||||||
|
let paths = format!("0 g\n{}f\n{RED}{}f\n", rect_path(0.0, 0.0, 30.0, 30.0), rect_path(10.0, 10.0, 20.0, 20.0));
|
||||||
|
let bodies = [
|
||||||
|
format!("0 Ae\n*u\n{paths}*U\n"),
|
||||||
|
// The paths in a group.
|
||||||
|
format!("0 Ae\n*u\n0 Ae\nu\n{paths}U\n*U\n"),
|
||||||
|
// The last path unpainted.
|
||||||
|
format!("*u\n{paths}{}n\n*U\n", rect_path(1.0, 1.0, 2.0, 2.0)),
|
||||||
|
];
|
||||||
|
for body in bodies {
|
||||||
|
let a = art(&read_ok(&layer(&body)).doc);
|
||||||
|
let NodeKind::Compound { children, .. } = &a[0].kind else { panic!("{:?}", a[0].kind) };
|
||||||
|
assert!(children.len() >= 2 && children.iter().all(|c| matches!(c.kind, NodeKind::Path { .. })), "{body}");
|
||||||
|
assert_eq!(fill(&a[0]).color(), Some(Color::rgb(1.0, 0.0, 0.0)), "{body}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn transparency_of_objects_and_groups() {
|
fn transparency_of_objects_and_groups() {
|
||||||
let art_ = format!(
|
let art_ = format!(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue