mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 15:51:56 +00:00
Merge pull request #5770 from dotCooCoo/fix/ai-editing-guides
.ai save: guides in the editing copy end with the guide operator only
This commit is contained in:
@@ -32,8 +32,8 @@
|
||||
//! global process color `… (name) tint model Xk`; Registration `1 1 1 1 ([Registration]) tint
|
||||
//! Xs`. Upper case paints the stroke.
|
||||
//! - State before each object: locked `A`, hidden `Xw` (`1` or `0`). An object's name follows it as
|
||||
//! an `/ArtDictionary` whose `AI10_ArtUID` is the name as an XML id. Guides are `(N) *`, the
|
||||
//! path, `(N) *` (`(n) *` when closed).
|
||||
//! an `/ArtDictionary` whose `AI10_ArtUID` is the name as an XML id. Guides are the path
|
||||
//! followed by `(N) *` (`(n) *` when closed), without the `(N) *` that §6 also puts before it.
|
||||
//! - Transparency: `mode opacity isolate knockout shape Xy` (the blending mode's number, Knockout
|
||||
//! Group 0 off, 1 on, 2 neutral), written when it changes: in a path's paint after its colors,
|
||||
//! before a guide, and after a group's end (`U` or `Q`) followed by `0 0 Xd` and `6 () XW`; a
|
||||
|
||||
@@ -978,6 +978,24 @@ fn artboard_display_marks_are_written() {
|
||||
assert!(ab.show_center_mark && !ab.show_cross_hairs && ab.show_video_safe_areas);
|
||||
}
|
||||
|
||||
/// A guide is its path followed by `(n) *` (closed) or `(N) *` (open), with no `(N) *` before
|
||||
/// it, and reads back as the same guide.
|
||||
#[test]
|
||||
fn guides_are_their_path_then_the_guide_operator() {
|
||||
let mut doc = Document::new(200.0, 100.0);
|
||||
let layer = doc.layers[0].id;
|
||||
let line = shapes::line(vectorcraft_geom::Point::new(10.0, 80.0), vectorcraft_geom::Point::new(150.0, 80.0));
|
||||
for path in [shapes::rectangle(Rect::new(10.0, 10.0, 50.0, 40.0)), line] {
|
||||
let g = Node::new(doc.alloc_id(), NodeKind::Path { path, rule: FillRule::NonZero, live: None, clipping: false, guide: true });
|
||||
doc.insert(Some(layer), usize::MAX, g).unwrap();
|
||||
}
|
||||
let p = program(&doc);
|
||||
let (closed, open) = (p.matches("\n(n) *\n").count(), p.matches("\n(N) *\n").count());
|
||||
assert_eq!((closed, open), (1, 1), "{p}");
|
||||
assert!(p.contains("0 Xw\n10 -10 m\n") && p.contains("10 -10 L\n(n) *\n10 -80 m\n150 -80 L\n(N) *\nLB\n"), "{p}");
|
||||
assert_eq!(lines(&read_back(&doc)), lines(&doc));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn effects_on_a_fill_are_reported_left_out() {
|
||||
let mut doc = Document::new(200.0, 100.0);
|
||||
|
||||
@@ -49,13 +49,16 @@ pub(crate) fn subpath(s: &mut String, xf: Affine, sp: &SubPath) {
|
||||
}
|
||||
}
|
||||
|
||||
/// A guide (§6): for each subpath, `(N) *`, its points, `(N) *`; with `closing`, a closed
|
||||
/// subpath ends `(n) *` (the painting operator that closes it first).
|
||||
pub(crate) fn guide(s: &mut String, xf: Affine, path: &PathData, closing: bool) {
|
||||
/// A guide (§6): for each subpath, `(N) *`, its points, `(N) *`. In `editing` data (see
|
||||
/// [`crate::ai_editing`]) a subpath is its points and `(N) *` alone, `(n) *` when closed (the
|
||||
/// painting operator that closes it first).
|
||||
pub(crate) fn guide(s: &mut String, xf: Affine, path: &PathData, editing: bool) {
|
||||
for sp in path.subpaths.iter().filter(|sp| !sp.anchors.is_empty()) {
|
||||
s.push_str("(N) *\n");
|
||||
if !editing {
|
||||
s.push_str("(N) *\n");
|
||||
}
|
||||
subpath(s, xf, sp);
|
||||
s.push_str(if closing && sp.closed { "(n) *\n" } else { "(N) *\n" });
|
||||
s.push_str(if editing && sp.closed { "(n) *\n" } else { "(N) *\n" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user