mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 16:33:22 -06:00
Fix #2920: an open path in a PDF-compatible .ai opens as drawn
Squashed from #4616 onto main.
This commit is contained in:
@@ -5,6 +5,7 @@ use vectorcraft_geom::Point;
|
||||
use vectorcraft_tools::{PointerEvent, PointerKind, ToolKey};
|
||||
|
||||
pub(super) mod adjust;
|
||||
mod ai_open_path;
|
||||
mod appearance;
|
||||
mod areafit;
|
||||
mod assets;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//! An open path in a PDF-compatible `.ai` opens as drawn (#2920). The PDF reader took a five-point
|
||||
//! open polyline whose points reach every corner of its own bounding box for a rectangle, so the
|
||||
//! zigzag below opened as a closed box. The file is written here from ISO 32000; it has no
|
||||
//! Illustrator editing data, so it opens from its PDF content as such an `.ai` does.
|
||||
|
||||
use serde_json::json;
|
||||
use vectorcraft_doc::NodeKind;
|
||||
use vectorcraft_geom::SubPath;
|
||||
use vectorcraft_testkit::pdf::{PdfPage, pdf};
|
||||
|
||||
use crate::*;
|
||||
|
||||
/// A 2 pt black stroke, no fill: a "W" whose middle peak rises only halfway. Its ends and the
|
||||
/// points beside them are the four corners of its bounding box; the peak is on none of them.
|
||||
const ZIGZAG: &str = "0 0 0 RG 2 w 80 38 m 80 21.75 l 60.571 29.875 l 40 21.75 l 40 38 l S";
|
||||
|
||||
fn subpaths(name: &str, content: &str) -> Vec<SubPath> {
|
||||
let bytes = pdf(&[PdfPage::new(120.0, 60.0, content)], None);
|
||||
let mut s = Session::new();
|
||||
s.execute("document.open", &json!({"name": name, "dataBase64": vectorcraft_format::base64_encode(&bytes)})).unwrap();
|
||||
let mut out = vec![];
|
||||
s.doc().unwrap().doc.walk(|n| {
|
||||
if let NodeKind::Path { path, .. } = &n.kind {
|
||||
out.extend(path.subpaths.iter().cloned());
|
||||
}
|
||||
});
|
||||
out
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_open_zigzag_in_an_ai_file_opens_open_with_its_five_points() {
|
||||
let paths = subpaths("zigzag.ai", ZIGZAG);
|
||||
assert_eq!(paths.len(), 1, "{paths:?}");
|
||||
let zigzag = &paths[0];
|
||||
assert!(!zigzag.closed, "the open path was closed: {zigzag:?}");
|
||||
assert_eq!(zigzag.anchors.len(), 5, "{zigzag:?}");
|
||||
let xs: Vec<f64> = zigzag.anchors.iter().map(|a| a.p.x).collect();
|
||||
for (got, want) in xs.iter().zip([80.0, 80.0, 60.571, 40.0, 40.0]) {
|
||||
assert!((got - want).abs() < 1e-3, "anchors at x {xs:?}");
|
||||
}
|
||||
// The peak is halfway up, not on the bounding box's edge.
|
||||
let ys: Vec<f64> = zigzag.anchors.iter().map(|a| a.p.y).collect();
|
||||
assert!((ys[2] - (ys[1] + ys[0]) / 2.0).abs() < 1e-3, "anchors at y {ys:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_same_zigzag_in_a_pdf_opens_open_too() {
|
||||
let paths = subpaths("zigzag.pdf", ZIGZAG);
|
||||
assert_eq!(paths.iter().map(|p| (p.closed, p.anchors.len())).collect::<Vec<_>>(), [(false, 5)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_rectangle_written_as_lines_still_opens_as_a_closed_rectangle() {
|
||||
let paths = subpaths("box.ai", "0 0 0 RG 2 w 40 21.75 m 80 21.75 l 80 38 l 40 38 l h S");
|
||||
assert_eq!(paths.len(), 1, "{paths:?}");
|
||||
assert!(paths[0].closed);
|
||||
assert_eq!(paths[0].anchors.len(), 4, "{paths:?}");
|
||||
}
|
||||
Reference in New Issue
Block a user