The tmp() helpers in apps/vectorcraft-cli/tests/cli.rs and fileio.rs
name their folder after the process id (vectorcraft-cli-test-<pid>,
vectorcraft-cli-fileio-<pid> in the temp folder) and never empty or
remove it. When a later run gets the same process id, it finds the
earlier run's files there. mcp_automation_roots then fails on Unix with
EEXIST (Os { code: 17, kind: AlreadyExists, message: "File exists" }):
its first symlink() call finds the link in/escape.svg that the earlier
run made. A stale output file can also let a fileio test read an
earlier run's export.
The first tmp() call in each test process now removes the folder and
creates it again empty. The roots test's body moves into
automation_roots(), and mcp_automation_roots_in_a_folder_an_earlier_run_left
runs it twice in one folder, emptying the folder in between as tmp()
does. Without the removal the second run fails with the same error.
perf --deep printed the memory at eight points of its run, and no row
showed memory that the run took and freed between two readings. With
--paths 2000, a release build on Windows printed 430 MB as its largest
row, and the process's peak working set was 612 MB. On Windows the
memory row after rendering the photos also printed its value 3 columns
right of the others: its name is 55 characters, and the name column is
52 characters wide. The tracked row for the photos printed its value 2
columns right of the other tracked rows: its name is 54 characters, and
their name column is 52 characters wide. In the budget table the handle
and segment drag rows printed their values 1 and 2 columns right of the
other rows: their names are 41 and 42 characters, and the name column
is 40 characters wide.
Each memory row now also gives the peak so far: the peak working set
(PeakWorkingSetSize, from the same GetProcessMemoryInfo call) on
Windows, and VmHWM from /proc/self/status on Linux. On macOS the rows
give no peak. A new last row gives the memory after the SVG export and
the save → open → save at the end of the run. The name columns of the
memory rows, the tracked rows and the budget table are 56, 54 and 42
characters wide. The help says on which systems the rows give the peak.
Docs: docs/target-app-parity.md.
document.open (and file.newFromTemplate) with a path relative to the
working directory took the SVG's folder from Path::parent(), which is
"" for a bare file name and was then dropped, so relatively linked
images were "not found" (and, linked by their bare name, not listed in
missingLinks either). A relative path is now made absolute first: its
folder is the working directory, as for the absolute path.
vectorcraft-cli convert printed only the export's warnings; what reading
the input left out now comes as importWarnings.
Fixes#1604
On Windows, perf printed "load average ?": load_average runs sysctl
or reads /proc/loadavg, and Windows has neither. The warning for a
busy machine could not print, so a run over budget on a busy machine
failed, where macOS and Linux warn and exit 0. perf --deep printed no
memory rows, because rss_mb runs ps. --help did not list --deep.
On Windows, perf now reads GetSystemTimes twice, one second apart,
and its first line gives the cores busy on average over that second
where macOS and Linux give the load average. It warns above three
quarters of the cores, as on macOS and Linux: with all 32 logical
processors of a test machine kept busy, the line read "cores busy
32.0" and a run with three budgets over exited 0. The --deep memory
rows give the working set (GetProcessMemoryInfo). Both calls use
winsafe 0.0.29, which Cargo.lock already lists for the desktop app;
the CLI depends on it on Windows with the kernel and psapi features.
The help lists --deep and says that a run over budget on a busy
machine exits 0. perf's report on macOS and Linux does not change.
Discord feedback: "EPS files are always rasterized: they open as bitmaps, in
other programs as vectors". Every EPS saved by Illustrator 2026 fell back to
its TIFF preview (`gcheck` was unknown), and cairo/Inkscape files stopped at
their first image (`status`), dropped masked images (ImageType 3) and failed
on mesh gradients; the warning didn't say where the program failed.
Fallback never silent:
- The warning names the PostScript error, the operator that raised it and
the named procedures it ran in, innermost first ("a PostScript error
(typecheck in `add`), in `inner` in `outer`"); errors caught by `stopped`
aren't reported. It reaches the status bar, document.open, app.open and
file.open (which now return document.open's result, so MCP's open_file over
the control channel gets it), and `vectorcraft-cli info` ("warnings").
- A file whose PostScript can't be read opens as its TIFF preview, else its
Windows metafile preview (as vectors, scaled to the bounding box), else its
EPSI bitmap. es @msg rows for the new messages.
Interpreter:
- Operators programs probe or use: gcheck/scheck, rootfont,
currentcolorrendering, currenthsbcolor, status, token, read,
bytesavailable, fileposition/setfileposition, resetfile, write*, pdfmark
(marks dropped, as Ghostscript does), execform, nulldevice, strokepath,
pathforall, user paths (ufill/ueofill/ustroke/uappend/upath/setbbox, the
encoded form too), setcachedevice2, findcolorrendering, cache, device and
VM queries, revision; (%stdout) (w) file gives a sink.
- `//name` is replaced by its value when read, inside procedures too.
- Tiling patterns become pattern swatches (their PaintProc drawn in pattern
space, one cell; uncoloured ones in the colour under them; makepattern
copies share one swatch); nested patterns stop at 8 levels.
- Type 3 fonts draw their glyphs (BuildGlyph/BuildChar, widths from
setcachedevice/setcharwidth) as outlines grouped per string, spaced by
ashow/widthshow/awidthshow/xshow/yshow/xyshow/kshow; glyphshow and
stringwidth/cshow use them.
- Shadings of types 1 and 4-7 become gradient meshes (data from arrays,
strings or files, packed or not, flags sharing edges), as fills through a
shading pattern too; sampled functions (type 0) are evaluated;
GradientMesh::coons/triangle are shared with PDF import.
- ImageType 3 masked images, interleaved by sample, by row or in separate
sources; ReusableStreamDecode reads its data when made; Flate/LZW PNG and
TIFF predictors.
- Bounded: DeviceN at 32 inks, sampled functions at 2^24 samples and 32
outputs, 4096 patches a shading, strokepath ignores dashes finer than 1e5
pieces, Type 3 glyphs nest 8 deep (a glyph that shows itself overflowed the
stack before the limit), 64-bit index maths for 32-bit targets.
Tests: a synthetic program per generator (cairo/Inkscape, its Type 3 fonts,
matplotlib, CorelDRAW, Affinity, LibreOffice, Ghostscript eps2write,
Illustrator procsets), meshes and function shadings, masked images, fault
messages, probing operators, metafile/EPSI previews, `//name`, user paths,
hostile patterns/glyphs/shadings (run against main, 12 of the 14 generator
and feature tests fail; CorelDRAW- and LibreOffice-style programs already
read there). The import fuzz vocabulary covers the new operators. Checked
against real files made here with Inkscape 1.4 (cairo) and Illustrator 2026
(its own format and the CS-to-CC compatibility formats; all fell back or
stopped early on main and open as vectors now; its Illustrator 8 format
needs the next commit); those files aren't committed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As the branch does for older tests: `panic!("…")` instead of
`unreachable!()` in test code (clippy.toml only allows unwrap, expect and
panic there), and the integration tests main added (CLI file I/O, render
gradient text and stroke geometry, SVG export suites) opt out of the
unwrap/expect/panic lints. No test logic changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>