The layers of PDF and PDF-compatible .ai files come from their
optional content groups, whose /Name is a PDF text string. The import
read a name without a byte order mark as Latin-1. Such a string is
PDFDocEncoding (ISO 32000-1 Annex D, Table D.2), which differs from
Latin-1 at 0x18 to 0x1F and 0x80 to 0xA0. A group named
(Art\205final) opened as a layer named "Art", U+0085, "final" instead
of "Art–final", and curly double quotes (0x8D, 0x8E) and the euro sign
(0xA0) became control characters and a no-break space.
text_string now reads such a string with the PDFDocEncoding table that
File Info already used for the document information dictionary. The
table moves from file_info.rs to import_scan.rs, and File Info reads
the information dictionary's strings with text_string.
When a PDF, PDF-compatible .ai or .ait opens, crates/pdf/src/file_info.rs
reads its File Info from the XMP packet with roxmltree, which parses
nested elements recursively and has no limit on their depth. A packet
with elements nested 10,000 deep (70 KB) overflowed a 1 MB stack, and
one nested 100,000 deep (700 KB) overflowed an 8 MB stack. A stack
overflow aborts the app.
File Info now counts how deep the packet's elements nest before roxmltree
parses it, and leaves out a packet nested more than 256 deep, as it
leaves out a packet that is not XML. The document information
dictionary then gives the File Info.
The MCP server's reader queues at most 64 lines for the engine and
stops reading past that until the engine catches up. The reply to a
line that is not JSON, or that is longer than the line limit, skipped
that check: while a call had run for less than the busy limit (two
seconds by default), or while the engine was behind, every such line
added a reply to the queue. In the new test, 192 lines that are not
JSON leave 192 replies queued on main.
These replies now wait for room as requests do, and still go out at
once when the running call has passed the busy limit.
SVG import checks each linked image's path with craft-docpath, and two
of its results were wrong, most visibly on Windows. A missing image's
link kept the path that craft-docpath returned, with its separators
rewritten: an href of /abs/photo.png became \abs\photo.png on Windows,
and SVG export with linked images writes that back as the href. A
folder that is not absolute, such as /tmp on Windows or a relative
folder on any system, made each relative href, and on Windows each
href rooted without a drive, resolve to a path that is not absolute,
so those images were not read. Two vectorcraft-svg tests failed on
Windows because of this.
A link now keeps the href as written (decoded) when the href resolves
to the same path without the SVG's folder, and keeps the path found
when it needs the folder: a relative path, or on Windows a path rooted
without a drive. A file: URL keeps the path it names. The folder is
made absolute against the working directory when it is not, as the
engine's reader does with the document's path. Hrefs that were refused
are still refused: paths on other computers, devices and URLs are not
read.
0.13.0's macOS release job failed twice at `stapler validate` right after a successful notarization
and staple: the CloudKit ticket lookup lost its connection (NSURLErrorDomain -1005, Error 68). Retry
the validate up to four times with a growing pause; a missing or bad ticket still fails.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reference app's Character panel has an anti-aliasing method for
type, with the options None, Sharp, Crisp and Strong. VectorCraft had no
such control or attribute.
The Character panel has an Anti-aliasing Method dropdown under
Character Rotation, and text.setFormat takes antiAlias. The method
belongs to the whole type object and to every frame of its thread. It
sets how the edges of the characters are drawn as pixels: on the
canvas, in raster exports and when the type is rasterized.
VectorCraft defines the methods. Sharp, the default, draws the edges as
before. None paints a pixel only where the type covers at least half of
it. Crisp shows a pixel that the type covers by a share c at 2c - 0.5,
and Strong shows it at 2c, each kept between 0 and 1. The opacity of
the type's paints is kept. In an export that supersamples its art, the
type is drawn at the export's own resolution, and the averaging keeps
its edges as the method draws them.
Type is drawn as Sharp when it holds inline graphics, when its own
fills or strokes include a brush stroke or a blend mode other than
Normal, when it overprints while Overprint Preview is on, and on the
canvas while it shows a substitution highlight. SVG, PDF and EPS export
are unchanged. The method is saved only when it is not Sharp. Reset
Panel sets Sharp, and it is now one undo step (it was two).
Docs: docs/mcp.md, docs/target-app-parity.md.
With Override Export on, action.batch gave each document.export,
document.exportSelection and document.exportForScreens step a path in
the destination folder. document.exportForScreens reads folder and has
no path parameter, so its files still went to the step's own folder,
or came back as data when the step named none. assets.export was not
overridden at all.
Override Export now gives a document.exportForScreens or assets.export
step the folder destinationFolder/<stem>, in place of the step's own
folder or an export preset's. Each source file gets its own folder,
named after the file without its extension, and each data set gets one
named <document>_<data set>. The export names the files in that folder
as it does outside Batch. Two data sets, or two source files whose
names without the extension differ, no longer write over each other's
files when their artboards or assets have the same names. Other export
steps are unchanged.
Docs: docs/mcp.md, docs/target-app-parity.md.
The FreeBSD job failed complete_languages_translate_every_message: zh-hans was
missing the four Links and Attributes messages this branch adds.
The merge created a state neither side had. This branch predates main adding
zh-hans to COMPLETE_MESSAGES, so its new messages had no Simplified Chinese; the
other 17 languages conflicted and were resolved as a union, while zh-hans merged
cleanly and silently without them. da, id, nl and zh-hant are also missing them
but are not on the completeness list, so they are left as they are.
Terminology follows the file's own: 编辑原稿 for Edit Original, 浏览器 for
browser, 不是文件 after {path} 不是文件夹. These want a native speaker's eye
before release; the test only proves the strings exist.