The editing copy of a PDF-compatible .ai wrote every symbol instance as
its art. Symbols are now written as symbols, in the form the .ai reader
reads them:
- Every symbol is defined in the setup, in a non-printing block after the
patterns: %AI14_BeginSymbol, its name, its art in the symbol's own
space, its registration point as AI13PatternRegistrationType and
%AI10_EndSymbol, each after the symbols its art uses. The nine points
are numbered 1 to 9 row by row from the top left, in the order the
scripting reference lists them. A definition is written the same
wherever its first instance lies. The symbol list after the palette
keeps the Symbols panel's order. A hidden root of a symbol's art is
written shown, as the canvas draws it.
- Each instance is a /SymbolInstance with its symbol's name and the matrix
that places the art (to ten decimals), followed by its name, opacity
mask, opacity and blending mode as a group's. In a symbol's art, the
matrices of instances, gradients and images are written in the
canvas's space about the canvas point of the ruler origin.
- Pattern fills in a symbol's art are written as their tiles cut to the
shape. A symbol whose definition holds such tiles, from its own
objects, a brushed stroke's brush art, a live object, an opacity mask,
a nested symbol or an inline graphic, has its instances written as
their art.
- Instances with a fill, appearance changes, isolation, knockout or
knockout shape of their own, instances of symbols with 9-slice guides
or pattern paint, instances in pattern tiles or in art cut to a
clipping object, instances scaled almost flat, instances that turn,
mirror or scale symbols holding type, live objects, instances written
as their art, shapes with rounded live corners or strokes written as
outlines or brush art (the canvas works these out again where the
instance puts them), instances that scale their symbol more than 100
times, nested instances included (numbers are written to four
decimals), and instances on the layers of a large canvas are written
as their art (the symbols are still defined). Symbols past the 4,096
the reader keeps are left out and their instances written as art; an
instance of a symbol the document doesn't have is an empty group.
9-slice guides, export types and the dynamic type are left out, and
linked images and type in a symbol's art are embedded and written as
outlines. Each comes with a warning.
The writer takes the reader's limit of 4,096 definitions (MAX_SYMBOLS)
and its symbol_art_member check, which now are pub(crate).
The editingData option's description lists what the copy now holds,
type written as text included.
Symbols and their instances:
https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/edit-symbols.htmlhttps://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/create-and-place-symbols.html
The nine registration points, in the order the scripting reference lists
them:
https://web.archive.org/web/20180219005134/https://wwwimages.adobe.com/content/dam/acom/en/devnet/illustrator/pdf/Illustrator-Scripting-Reference-JavaScript-cs6.pdf#page=252
Tests: the round trip of symbols, nested symbols and instances in every
state, symbols whose art is a group with a state of its own, images and
gradients in a symbol's art, every registration point, symbol names with
special characters, duplicate and missing symbols, a symbol first used
deep in opacity masks, symbols past the reader's count (one found only
while its holder's art is written included), a large canvas, symbols
with pattern fills (directly, nested, in an opacity mask, through an
inline graphic and through a brushed stroke), scaled instances of
symbols with an outside stroke, rounded live corners, type, a blend, a
tiny or thin object, an ellipse or an instance of a symbol with 9-slice
guides, a symbol whose root is hidden, instance matrices from a fixed
seed, a second write of what is read back giving the same bytes, the
forms written, the instances written as art and the options reported.
Docs: docs/file-format-parity.md, README.md, ROADMAP.md, docs/gaps.md,
docs/roadmap.md and docs/target-app-parity.md describe the editing copy
a saved .ai holds.
A stacked style with a single gradient took the object's own gradient
fill whenever the object had one, even where the drawn look placed the
gradient elsewhere. A stack now always takes the placement of its drawn
look, which it already requires for each of its gradients.
- Auto leading stays auto: each line takes the paragraph's share (key 7)
of the largest type on it. The leading was the first two lines'
distance for every line, so 10 pt lines under a 15 pt heading came in
18 pt apart.
- The paragraph's hyphenation options (keys 10 to 15) are read.
- Area type of one frame whose last lines the file sets, but which don't
fit here (the fallback font, or a descent past the frame's bottom),
gets a frame taller from its bottom (vectorcraft_text::fit_source_lines),
with a warning.
A user's .ai whose type differed from its page by 6.6%, so that it opened
from its PDF part with each line its own text object, now opens from its
layers.
In Justify Left, Center or Right, only the paragraph's last line keeps its
alignment; a line that a soft return (U+2028) ends is spread to the frame's
edges like any wrapped line. Illustrator's own layout in a user's .ai sets
such lines justified, and VectorCraft left them ragged.
A .ai or EPS whose editing data defines symbols but has no layers came
in as its PDF part or page without symbols, and Other Library in the
Symbols panel listed none. Such a file, and a file read as its PDF part
or page because its layers can't be used, now gets the symbols its
editing data defines before its first layer, as a file read from its
layers does: File > Open shows them in the Symbols panel in the order
of the symbol list, and Other Library lists them in a library panel.
- Each symbol keeps its registration point. A symbol that holds an
instance of a symbol the file doesn't define is left out, and an
object linked to a listed graphic style keeps the link.
- The symbols' art takes ids of the document, the art of opacity masks
in it included, and the images it shows come with it. Instances
drawn too deep are removed with the usual note.
- The global and spot colors the art is linked to come in as swatches.
A color whose name another swatch has takes that swatch's place when
it is a default swatch of a file without a palette; otherwise it
comes in under a free variant of the name ("Ink 2"), which the art
then names.
- Symbol art keeps the editing data's units, as in a file read from its
layers, so in a file in larger units its linked graphic styles are
drawn at the scaled size and the symbol art is not.
- The art of the patterns a palette or brush brings into a file read as
its PDF part or page now also takes new ids for its opacity masks.
Part of #3349
An object opacity or blend mode set on a path directly in a graph series, and
the blend mode of its topmost visible fill or stroke, were lost when the graph
was drawn again. The graph now stores them per series next to the row opacity
it already stores, and puts them on every path directly in the series when it
draws the series again.
- transparency.set and object.setProps store the object's opacity and blend
mode. A value the mark already has still replaces the value another mark of
the series stored.
- appearance.clear, appearance.transfer, appearance.copyFrom with Transparency
picked up, graphicStyle.apply without add and graphicStyle.redefine store
the object's opacity and blend mode they leave on the mark.
- The other Appearance and style commands store them when they change them
on a mark.
- Every command that stores the opacity of the topmost visible fill or stroke
also stores its blend mode. A Filled Lines band's outline takes the stored
stroke opacity and blend mode and keeps its black 0.25 pt stroke.
- An opacity and blend mode are stored as a pair from the edited mark:
setting only the opacity of one mark also stores that mark's blend mode.
- A graph design's copy in a series keeps its own values.
Docs: docs/mcp.md, docs/target-app-parity.md.
What a data source procedure allocates stays counted: only the sample planes,
the decoder's copies of the strings a procedure returns, and the split buffers
of an interleaved masked image stop counting once the image is decoded.
Applying a graphic style, Redefine Graphic Style, Default Fill and Stroke
and Swap Fill and Stroke on a path in a graph series changed the path
but not the paint the graph stores for the series. When the graph was
drawn again, the series went back to its earlier paint.
These commands now store the mark's topmost visible fill and stroke on
the graph, in the same undo step as the command:
- graphicStyle.apply stores the paint, weight and opacity of both kinds
of row. With `add` it stores only the kinds of row that are visible
in the style.
- graphicStyle.redefine stores the paint, weight and opacity of the
marks still linked to the style.
- paint.default stores the white fill and the 1 pt black stroke, both
opaque.
- paint.swap stores the swapped paints and the stroke weight and keeps
the stored opacity. It swaps the topmost rows even when they are
hidden, and a hidden row it swaps is not stored.
The rule for each kind of mark is the one docs/mcp.md gives for the
Appearance commands. docs/mcp.md also says what the graph does not
store from a graphic style and that a series group given to a graphic
style command is not stored. The params text, docs/mcp.md and the
Graphs line in docs/target-app-parity.md list the commands.
Each evaluation of a sampled function copied its DataSource and read
every tap combination without counting that work: a shading evaluates
its function once per stop, so a long DataSource or many interpolated
inputs did far more work than the budget charged. Both now count. The
nearest-sample fallback is kept at the last sample, which a fractional
Size could put it past.
An Art brush object whose last field had neither 15 numbers nor the
older form's 8 came in with default settings. It is now left out like
other brushes whose values can't be read. An older-form Art brush keeps
the Art brush's default colorization, as the note says.
A run of gradient strips under a clip larger than the strips became the
clip path filled with the gradient, painting where the strips did not.
The clip path now takes the gradient only when every point of the clip
lies inside the run; otherwise the gradient stays clipped to the strips'
area.
A preferences file from before the Help Bar setting gets `help_bar` from
`status_bar` when it is read. A save that changed only the status bar
left `help_bar` out of the file, so the next start hid the Help Bar with
the status bar. A save now writes `help_bar` whenever the file lacks it,
and keeps a value another window saved.
Docs: the UI evidence list, the UI checklist and the M14 row record
Window > Help Bar.
paint.setFill, paint.setStroke, paint.none, Apply Fill to Stroke and Apply
Stroke to Fill stored a series' paint on the graph. appearance.setItem, the
Eyedropper, appearance.transfer, Clear Appearance, Reduce to Basic Appearance
and the add, remove, move and duplicate row commands stored no paint or weight.
An Eyedropper pick of a blue fill at 40% onto a red column drew red at 40%
after the next redraw.
These commands and Show All Hidden Attributes now store the paint and weight
of the topmost visible fill and stroke of a path directly in a series group,
in the same undo step. A color, weight or opacity that a command writes to that
row replaces the stored value even when the mark's own value does not change. A
row that has no paint before and after the command does not change the stored
paint. These commands store no stroke for a series that draws Filled Lines
bands, and a band no longer takes its color from an empty stored stroke.
The stored opacity also comes from the topmost visible row: hiding a top row
stores the row under it, and an opacity set on a hidden top row is not stored.
Follows #5501.
The earlier paragraph said document.export takes any key when its description names none. The export commands refuse an unknown option key, so the paragraph now lists them as an exception and keeps document.save as the example that takes any key.
document.export, document.exportSelection, document.serialize, app.export
and file.export took {noSuchOption: true} and wrote the file with no
warning. They now refuse a key that no format lists in document.formats,
and name the nearest key when one is close. document.exportPdf,
document.pdfSettings and pdf.preset.save refuse a key PDF doesn't take,
document.exportEps one EPS doesn't take and document.exportDxf one DXF
doesn't take. Each refuses an unknown key inside an option object it takes,
such as marks.useDocumentBleed, and names its path.
A key that only another format reads, such as {format: pdf, quality: 80},
is still ignored: docs/mcp.md says one object can carry several formats'
options. The check runs for callers (the control channel, MCP, the CLI).
A journal or a recorded action isn't checked, and a saved PDF preset with
a key that is no longer read still loads.
document.formats now also lists PDF's thumbnails, fastWebView and
viewAfterSaving.
edit.copy and edit.cut chose the artboard route by the tool chosen, which
the journal does not record. A replay in a new session acted on the objects
selected there, or stopped with "nothing selected" when there were none.
With the Artboard tool chosen, both now record selectedArtboards and art in
the journal entry. A given selectedArtboards runs the artboard route with
any tool and needs only a document. A recorded action leaves both values
out, so it follows the tool chosen when it plays. Cut and Copy of objects
record nothing new.
request, execute, commands and screenshot move onto the shared crate (storytold/craft-libs#413): a timeout on every call, the screenshot's PNG also in data, and docInspect and uiInspect beside them. A call the page gave up on gives up its request if the app has not started it, so the app skips it. openFile, captureDownloads, files, readFile and inspect stay VectorCraft's own, on the same object.
The legacy reader skipped `TV`, `Tv`, `Ty` and `TY` of section 15.3.4 of
the version 7 file format specification, so type set with `1 TV` opened
horizontal.
- `TV` sets a text object's writing direction. VectorCraft keeps one
direction for each text object, the one in force at its first
character, with a warning when a later character has another.
- `Ty` marks a Kumi block as a Tate-chu-yoko run, which is VectorCraft's
own mapping, and `TY` does the same in horizontal type. A `TY` block in
vertical type opens unmarked. Two blocks with nothing between them open
as one block.
- `Tv` sets Standard Vertical Roman Alignment.
All four are modal, and an operand other than 0 or 1 leaves the value as
it was.
Docs: docs/file-format-parity.md.
After Select All in threaded text, the Justification dialog kept the edited
frame's selected range when that frame was no longer threaded at OK. A thread
broken after the frame moves the rest of the story into it, so the paragraphs
past the old range kept their values. The dialog now drops the range and
changes every paragraph in that frame.
With mixed indents, the Tabs panel sends one text.setFormat per paragraph,
addressed by frame and byte offset. Threaded text reflows after each step,
so an indent that made earlier paragraphs wrap onto more lines moved text
into the next frame, and the later steps landed on the wrong paragraphs or
on none. The steps now run from the story's last paragraph to its first, so
each step's offset comes before every change already made.
After Select All in threaded text, the Tabs panel's indent markers read
the indents of the edited frame alone. When another frame's paragraphs
had a different left indent, a marker drag changed them by the edited
frame's values, or left them alone. The markers now take every
paragraph of every frame in the story, so each paragraph keeps its own
left indent or first-line position.
The Justification dialog kept the frames of the story from the moment
it opened. OK now acts on the frames in the edited frame's thread when
it is pressed, so a frame that left the thread while the dialog was
open is not changed, and a frame that joined it is.
After Select All in threaded text, the panels read the frames from the
list saved at Select All. A frame that had left the thread still took
Paragraph, Tabs, Justification and Text Styles changes, a frame added
later did not, and when the first saved frame had left, Character,
OpenType and font changes went to that frame alone.
text_story now reads the frames of the edited frame's thread from the
document. Locked and hidden frames stay in the story.
An object read as its drawn look counted in the import's "came in as
their drawn look" note when it was on the page or in a kept symbol, but
not when it was in a pattern's art or a brush's art. A file whose only
such objects were in a pattern or a brush opened without the note.
- A kept pattern's drawn looks count, once for each pattern name: a
definition that a later one of the same name replaces no longer counts.
- A brush's art counts once a brush that is kept uses it; art no kept
brush uses adds nothing.
Q restores the painting state but not the transparency (Xy): the writer
sets Xy only when the next object's state differs from the last one it
wrote. Restored at Q, type after a clipping group following a Screen glow
drew in Screen and nearly vanished on a light background.
A blend whose spine was never edited has only its keys in the editing
data, no spine part. Its spine is the straight lines between the keys'
centres in the record's order; read as such, the blend comes in live
instead of as its drawn steps.
Illustrator 24 writes its symbol definitions ahead of %AI9_BeginArtStyles,
so a styled object inside a symbol found no style and came in as its drawn
look. The pre-pass that finds swatch names now also keeps the first
top-level art styles section, which the reader parses before the art.