Skip to content

Feat/vectorcraft placed documents - #564

Merged
bflatastic merged 7 commits into
storytold:mainfrom
Haven-King:feat/vectorcraft-placed-documents
Oct 8, 2026
Merged

bflatastic merged 7 commits into
storytold:mainfrom
Haven-King:feat/vectorcraft-placed-documents

Conversation

@Haven-King

Copy link
Copy Markdown
Contributor

What and why

Place a VectorCraft document in another as a placed document: one locked object showing an artboard of the file, linked to it and updated when it changes. Until now, placing a document copied its art in as an editable group, which didn't follow the file and added every copy's paths and resources to the document.

Breaking change: file.place of a .vectorcraft file from a path now links it by default. Pass link: false (Place's Link checkbox off) for the editable copy. Placing from dataBase64 still gives a copy. Files dropped on the canvas follow the same rule (Shift embeds).

  • Placing: File > Place with Link on (file.place's page and crop: "bounding" apply). The Link tooltip explains linking and embedding for the kind of file picked: images, VectorCraft documents, or both.
  • Output: vectors in SVG, PDF, EPS, EMF and DXF. Placed documents inside a placed document are read from their own files, up to 8 levels deep, so documents that place each other stop there.
  • Links: check, update, relink, Update Links on open, Link Info (the artboard's size), Placement Options and Edit Original (opens the file in a new tab) work on placed documents. Saving a document in the app updates the open documents that place it.
  • Break Link: a new Links panel button (links.embed). An image keeps its pixels; a placed document becomes the editable copy that placing it without Link gives, its symbols, patterns, swatches and images joining the document. Object › Expand does the same.
  • Speed and size:
    • On screen, placed documents draw from bitmaps cached per zoom level, made in the background and shared by every copy.
    • Saves keep only a small preview of each file (JPEG when opaque) unless Include Linked Files is on; output reads the file again, and falls back to the preview with a warning when the file is gone or changed.
    • On a 200-card sheet with distinct sources, compared with editable copies: the sheet draws in 1.2 ms instead of 836 ms, opens in 3 ms instead of 50 ms, and the file is 3.2 MB instead of 4.6 MB. PDF export is about the same (0.9 s).
  • File format v4: data of 8 KB or more goes after the JSON instead of in it as base64. v3 and older files still open, and saving as v3 or older writes placed documents as groups.
  • Widgets: a new check_tip puts a checkbox's tooltip where egui hit-tests it; a tooltip on a scope around the checkbox never shows.

Each commit builds on the previous one and can be reviewed alone: widget -> format v4 -> model and exact drawing -> placing and output -> Links commands -> on-screen bitmaps -> UI.

Also as a note, this is an example of a behavior that all of the image-targeting ArtCraft projects would likely benefit from. I don't intend on porting it to the other two, I'm just pointing it out as a point of evidence towards rearchitecting the projects.

How it was tested

  • engine/src/tests_placed_document.rs (16 tests): placing linked or as a copy, output in every format, saved previews, nested documents, loops, errors and junk parameters, update, relink, Update Links on open, Break Link (compared with an unlinked placement), Expand, refresh on save, Link Info.
  • render/src/tests_placed_document.rs: exact drawing, the placeholder then the bitmap, shared bitmaps, drawing from the preview, a document that places itself.
  • doc unit tests (resources, nesting, the cache, previews), format/tests/native_v4.rs (round trips, older versions inline, damaged offsets refused), ui-egui/src/tests_place.rs (Link on by default, the tooltip for each kind of file, Edit Original).
  • Checked by hand in the app: placing, the Link tooltip, Link Info, Edit Original, the 200-card benchmark sheets.

One test fails, and it isn't this branch's: cmd::typecmd::area_tests::leading_model_is_set_per_paragraph_and_saved_only_when_top_to_top (crates/engine/src/cmd/typecmd.rs).

  • The failure: setting leadingModel: "emBoxTop" on the test's CJK text (一\n二) leaves the text's bounds unchanged.
  • Why it isn't this branch: the test came from main (46dc8b1, "Type: Top-to-Top Leading"), and this branch touches neither the type code nor that test.
  • Unconfirmed cause: these runs had no CRAFT_FONTS_DIR, so there may be no CJK font with em-box metrics to move the line. I haven't checked whether it also fails on main.

The full suite was run with --no-fail-fast, and that test is the only failure.

Checklist

  • cargo xtask ci passes (fmt, clippy, tests, assets, brands, layers, wasm). Everything passes except the one test above.
  • No panics in shipped code: no unwrap(), expect(), panic!, unreachable!, todo! or
    unimplemented! outside tests, and no unchecked indexing on data from files, parameters or
    messages. Errors are returned as Result and shown to the user
    (why and how).
  • Clean-room: nothing copied from Adobe products or GPL/AGPL code (AGENTS.md).
  • Every new asset has a row in ASSETS.md (there are none).

@Haven-King
Haven-King force-pushed the feat/vectorcraft-placed-documents branch from 03c5e82 to 99d81b7 Compare October 8, 2026 19:19
@Haven-King
Haven-King force-pushed the feat/vectorcraft-placed-documents branch from 99d81b7 to 5e7af3f Compare October 8, 2026 19:22
@bflatastic
bflatastic merged commit c26c4a2 into storytold:main Oct 8, 2026
@bflatastic

Copy link
Copy Markdown
Member

Merged, thank you @Haven-King! This is a big, carefully built feature. Placed VectorCraft documents stay linked and update when their file changes. They export as real vectors everywhere and fall back to previews with a warning. A save for an older version writes them as plain art, and the Links panel and its commands cover them. The engineering underneath is just as careful: bounds-checked v4 data after the JSON, the 8-level nesting stop, hash checks on re-read files, bounded LRU bitmap caches with poison-safe locks, and background renders left out of wasm.

What I checked before merging:

  • Full CI on the integrated tree.
  • In the running app, place a saved .vectorcraft (one linked Placed Document, Links: ok). Edit and save the source, and the host's copy updated by itself. Save for v3, and it reopens as a plain clip group of the art. A fresh save converts to SVG as vectors with no warnings.
  • Over MCP, file.place and links.list.

Your rebases kept the code commits identical, which made re-checking easy. One follow-up we'll do separately: linked files (images on main too) are read with no size cap, so a document naming a huge file could exhaust memory.

If you'd like to chat with us and other contributors, come join https://discord.gg/artcraft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants