Shippori Mincho (8.7 MB) and its licence leave assets/fonts. Japanese fonts now
come from storytold/craft-fonts when built with CRAFT_FONTS_DIR (never a
Cargo.toml dependency): crates/fonts/build.rs embeds its manifest as
designcraft_fonts::CRAFT_FONTS. Native builds embed all four fonts; wasm32
embeds BIZ UDPGothic Regular only (web size budget).
- UI (egui): the Jpan faces at the end of every family, BIZ UDPGothic first
(Bold first in the semibold family).
- Documents: FontDb loads them after the bundled fonts, Mincho first, so they
are the Japanese fallback ahead of system fonts; SVG text gets them too.
- Vertical alternates test runs on every craft-fonts face and skips when
CRAFT_FONTS is empty; new UI no-tofu test and without-craft-fonts tests.
- FreeBSD CI tests with craft-fonts; release.yml builds every platform with
CRAFT_FONTS_DIR + CRAFT_FONTS_REQUIRED=1 at a pinned commit, packages carry
OFL-<family>.txt; NOTICE, ASSETS.md, AGENTS.md/CLAUDE.md, README, ROADMAP.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Release builds add an arm64 MSI and portable zip, cross-compiled on the x64
runner (signing and WiX as for x64). package.ps1 checks each binary's PE
header before packaging: Machine must match -Arch, the app must be a GUI
program and the CLI a console program. It skips the CLI smoke run when an
ARM64 build can't run on the host. A new Windows ARM64 workflow packages the
ARM64 MSI, installs it on a Windows 11 ARM64 runner, checks both installed
exes are ARM64, runs the CLI, and uninstalls. Ported from printcraft#66.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- view.snapPreferences {alignEdges, alignCenters, smartDimensions,
smartSpacing, zone} sets the smart guide options; the Preferences
dialog goes through it, so the control channel and MCP reach them.
- Smart guide, gap and measurement colours come from theme::Tokens.
- Remove the unused closest-target helper (snap_rect and friends).
- Drop the agent planning docs (docs/superpowers) and the .worktrees
ignore line; ROADMAP entry for smart guides and snapping.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shift plus Alt restores the aspect from the original center after the size snaps. A line keeps the runner delta on both axes. Dimension guides are redrawn on the committed side. Grouped own size decomposes the absolute transform once.
FontDb cataloged the system fonts only when a character needed a fallback
(nothing else calls load_system_fonts), so a document set in an installed
family was composed in Source Sans 3, and font.list and preflight reported
the family missing (#22).
Every lookup by family name now waits for one scan of the font folders per
session, as VectorCraft does since #130: the app starts the scan in the
background at startup, other processes run it on first use. The scan reads
only each file's table directory and name table, and skips folders it has
already read, so a symlink loop can't hang it. has_family counts installed
families. FontDb::with_font_dirs and system_font_dirs let tests use their
own font folder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
preflight.run measured every placed graphic's "pixels", which for a PDF or
SVG is only the size of its screen preview, so a vector logo placed at its
own size was reported as low resolution:
{"kind": "lowResolution", "message": "logo.pdf: effective 72 ppi (< 150)", "severity": "warning"}
Placed PDF and SVG pages export as vectors; the effective-resolution check
now applies to raster images only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`designcraft-cli commands | head -1` panicked and exited with status 101:
thread 'main' panicked at library/std/src/io/stdio.rs:1168:9:
failed printing to stdout: Broken pipe (os error 32)
println! panics when stdout is closed. Output now goes through outln!, which
ends the program with status 0 on a broken pipe (the reader has what it
wanted) and reports any other write error on stderr with status 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CMYK rewrite matches krilla's exact output; if that ever changes,
the export says so instead of silently writing RGB groups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krilla gives every transparency group it writes a DeviceRGB blending space,
including the group around a placed PDF page:
/Group<</Type/Group/S/Transparency/I true/CS/DeviceRGB>>
A print file therefore carried DeviceRGB (forbidden by PDF/X-4 under a CMYK
output intent) and blended CMYK art through RGB: a placed logo's black,
C91 M78 Y61 K97 in its own file, printed as C72 M67 Y67 K88. When the
document's transparency blend space is CMYK (the default for print) or the
export is PDF/X-4, the groups are rewritten to /CS/DeviceCMYK in place and
at the same length (the optional /Type/Group gives the room, the rest is
padded with spaces), only inside object dictionaries found through the
cross-reference table, so every offset stays valid. Booklets get the same.
Books merged by merge_pdfs are not covered.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PDF/X-4 export (PDF 1.6) of a page with a placed PDF 1.7 (VectorCraft's
default, and most tools') failed at the very end with
designcraft-cli: PDF writer error: Pdf(PdfDocument(PdfDocumentRepr { .. }), VersionMismatch(Pdf17), None)
krilla refuses to embed a PDF newer than the file it writes. PDF 1.7 changed
nothing in how a page draws, so a 1.7 file now goes in as 1.6 (its header
relabelled, as qpdf --force-version=1.6 does) with a warning. A PDF 2.0
file, or one whose catalog declares 1.7, fails the export with a message
naming it. hayro-syntax moves from dev-dependencies to dependencies (krilla
already builds it) because the check names its PdfVersion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Paper] was written as DeviceRGB white (`1 1 1 rg`) even in print documents
and PDF/X-4 files: an RGB object in a CMYK print file, which print preflight
rejects. For the Print intent and for PDF/X it is now `0 0 0 0 k` (CMYK, no
ink, still knocking out what lies below); Web and Mobile documents keep RGB
white.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
named_targets reads ids/id as targets() does, so {ids: [], id} can't
pass the gate and then run on nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A command that documents ids (object.textFrameOptions, transform.rotate, ...)
acts on the objects a call names, yet its enabled check looked only at the
selection. With a text caret or nothing selected, {"ids": [5]} failed with:
command `object.textFrameOptions` is not available right now: nothing selected
Execute now lets such a call through when every named object exists, and
says "no object with id N" when one doesn't. transform.set, object.arrange
and edit.stepAndRepeat, which already acted on ids, now document them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
frame.create's text and text.insert kept CR and CR LF as characters, so text
written with InDesign's, classic Mac or Windows line ends ("One\rTwo") became
a single paragraph, and paragraph formatting (spaceAfter) never applied
between the parts. They now become \n, the paragraph separator, as edit.paste
and text import already did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anchor and focus are byte offsets into the story text, as find.find reports
them, but the params doc said only {story, anchor, focus}. A script that
counts characters (Python's len()) selects too little after the first
accented letter: with "Matemática Básica" and focus 17, type.char left the
last two letters out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes the Windows installer: the Start Menu shortcut and Add/Remove Programs icon were blank, and the shortcut description was wrong. Release builds no longer open a console window behind the app.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The MSI Icon id had no .ico/.exe extension, which Windows Installer needs for
advertised shortcuts and ARPPRODUCTICON, so both showed a blank icon. Release
builds of the desktop app are now GUI-subsystem (no console window; the CLI stays
a console program), the shortcut/summary description names what DesignCraft does, and
packaging-lint rejects an Icon id without an extension. Found in printcraft#57.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use the document model boundary helper for explicit selections and retained selections after story replacement. Cover editing and caret movement through the command API.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
The UI theme included the 8.7 MB font a second time; it now uses
designcraft_fonts::JAPANESE_FALLBACK (release binary 72 MB -> 63 MB).
The ROADMAP note joins the Interface language entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Real-file test oracles live in storytold/photocraft-corpus, explained in
craftrules standards/test-corpora.md. Never commit large binary fixtures
here; fetch them pinned and sha256-verified.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A FreeBSD workflow builds and tests the workspace in a FreeBSD 14 VM
(vmactions/freebsd-vm) on pushes to main, dependency changes and on
demand. The X11 backend choice for file drag-and-drop covered only
Linux; FreeBSD desktops use the same X11/Wayland stack, so it now applies
to all(unix, not(macos)).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>