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 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.
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.
prefs.set did not check the folder given as recoveryFolder or pluginsFolder,
beyond the automation roots check, so a control or MCP caller could save a
folder that does not exist, a file, or a folder the app cannot use. Only the
Preferences dialog checked the folder itself.
The dialog's folder checks move to the engine, and prefs.set runs them after the
automation roots check. A folder that fails returns the same error the dialog
shows, and no preference changes. An empty value, an omitted value and a folder
the preference already holds are not checked. The Wasm build skips the check, as
the dialog did. The dialog's OK now gets the check from prefs.set, and Choose…
calls the moved check directly.
The check tested one box per source segment for every candidate hole or
island. It now searches a tree of the segments' bounding boxes, built once
when the first contour is checked. The answer for each contour is the same,
so the output paths do not change. MAX_OFFSET_SEGMENT_PAIRS does not change.
With the Artboard tool, the canvas context menu lists the entries of the
public Use the artboard context menu page in its order, in place of the
entries for objects and the view. Lock Artboards and Unlock Artboards are
two submenus. An entry that cannot run is left out, and Undo and Redo stay
dimmed. A right-click on an artboard that is not selected selects it alone
first, and the menu measures the art for Delete Empty Artboards and Fit to
Artwork Bounds once, at the right-click.
Cut, Copy, Duplicate Artboards, Rename, Delete Artboards, Lock Selected,
Unlock Selected, Fit to Artwork Bounds, Switch Orientation and Export act on
the artboards the tool has selected, else the active one. docs/mcp.md lists
what the other entries act on.
- artboard.rename renames in one undo step and numbers several names. The
menu's Rename opens a dialog that runs it, and the Artboards panel's name
field runs it too.
- artboard.switchOrientation swaps width and height and keeps the top-left
corner, skipping square and locked artboards.
- artboard.selectAll chooses the tool and selects every artboard.
- edit.paste takes artboardsAt, and the menu's Paste centers copied
artboards on the right-click's point.
- The menu's Cut and Copy run artboard.cut and artboard.copy. In the desktop
app those commands publish to the system clipboard, and the menu shows the
Cut and Copy shortcuts for them.
- artboard.fitToArt and the panel's name field record no undo step when
nothing changes.
artboard.duplicate, copy, cut, rename and switchOrientation take their
artboards from the tool's selection when a call names none. Each now records
them in the journal as selectedArtboards, which a replay reads and a recorded
action leaves out. The copy commands also record art. switchOrientation
records scaleArt, and it takes patterns and lockedAndHidden and records what
its artboard.setProps step resolved for them.
While the Artboard tool is in use, a command chosen from any menu or the
command palette moves the tool's selection as the Artboards panel does:
artboard.new makes the new artboard active, artboard.duplicate selects the
copies, and artboard.delete and artboard.deleteEmpty make a remaining
artboard active.
Only type kept an art style that stacks several fills or strokes, or gives
one its own opacity or blend mode, as a live appearance; paths came in as
their drawn look. A path or compound path now takes such a style (solid
colours and gradients, strokes without a brush, no effects on the items,
object effects any object takes that don't move the outline) when every
gradient is its own swatch painted by the drawn look, which gives each its
placement. Anything else keeps the drawn look.
A sampled function (type 0) of two or more inputs took the nearest
sample, so a function-based shading over one came in as flat blocks.
It is now interpolated multilinearly, and with Order 3 by cubics through
the samples, kept in its range (PLRM 3rd ed. section 3.10.1). An axial or
radial shading over a linearly interpolated sampled function of one
input has a stop at each sample.
The fitter accepted a piece at depth 14, or with fewer than six points,
whatever its error, so a traced outline could stay farther than the
tolerance from its points. Synthetic 2 px block noise at Paths 100 and
Corners 0 kept a piece 2.7 px off at a tolerance of 0.1.
Such a piece is now accepted only when each point is within the tolerance
of the curve. Otherwise a short run is cut at its worst point, down to
two points, and a run at the depth limit is cut in the middle, which keeps
the recursion shallow. Every other piece is unchanged. Noisy art can get
more anchors.
a_traced_pixel_that_straightens_to_no_area_... now traces at Paths 80. At
Paths 90 that pixel's no-area result came from pieces over the tolerance.
save_file's note for a key in `options` that the written format doesn't
read named every .ai file a PDF-compatible .ai, also when the save wrote
a version 7 file (`aiVersion: "7"`) or one without PDF content
(`pdfCompatible: false`).
The save itself now writes that note, beside its note on a top-level
`compress`, `version`, `preview` or `precision`, and names the file it
writes, including when it reuses the options the document was last saved
with. save_file returns the save's reply unchanged, and
`run_command document.save` and the other save commands give the same
notes.
The reader put an opacity mask's art in a group every time, so a mask
made from one path came back from a saved .ai as a group holding the
path, while Make Opacity Mask keeps one object as the art. This also
changes how existing files with single-object masks open, because
the editing data of a .ai, an EPS and a PDF goes through this reader:
the art is the object.
A hidden object or a guide stays in a group, because the canvas draws
the art's root whether it is shown or not and whether guides show. A
clipping path alone stays a clipping group.
The editing copy writes a plain group of one object as a group (u, the
object, U), so it reads back as a group. Its other plain groups are
still written as their members. Hidden mask art is written shown,
because the canvas draws it and a group read back would not.
Encryption keeps the /ID already in the trailer and draws one from the
seed only when there is none. A PDF 1.3 export draws no random bytes, so
it repeats with SOURCE_DATE_EPOCH set, while PDF 1.4 and later differ
between runs. Their random bytes are in the encryption dictionary and,
at PDF 1.6 and later, in the AES initialization vectors.
The panel menu's item added the artboard and left the active artboard
where it was, while the panel's button, the Control bar and Properties
made the new one active. All four now call one helper. With the Artboard
tool, the new artboard is then the only one selected.
The sample planes an image is decoded from, and the strings a procedure
data source hands back to fill them, are freed once the image is
decoded, so they stop counting against the 1 GiB budget then; the pixels
kept still count. A file of many images whose procedure returns one
large buffer each time no longer runs out of budget.
When the link-watch worker unwound before storing its stamps,
poll_link_scan returned None on every frame and left link_scan set. The
app then asked for a repaint every 100 ms and start_link_scan returned
early, so the app did not look for changed linked files in the
background again for the rest of the session.
poll_link_scan now clears a look that has ended without stamps. The new
ended_without_stamps helper holds the slot's lock across its read of the
stamps and its read of the ended flag, so a look whose worker stores its
stamps during the check is applied. The app goes back to its two-second
wake, and the next look starts on schedule. A look still running and a
look that stored its stamps behave as before.
Art brush objects whose first number is 1, as older files write them, have one
field fewer before their numbers and 8 numbers at the end. The reader wanted
exactly 15 and left every such brush out with a note, though an Art brush is
read from its art's name alone. Scatter brushes still need all 15 numbers.
A page that paints a gradient as a row of abutting one-colour strips (as
Level 2 writers draw smooth shades) imported as hundreds of separate
fills. Each anti-aliased on its own, they left seams where the art below
showed through every shared edge (PDF 32000-1 §10.6.4, conflation): thin
stripes, and a pale tint over strips a pixel or two wide. An Illustrator
EPS whose page drew its gradients that way then differed from its layers
and opened as its page with empty layers.
A run of at least six such strips under the same clips, side by side in
one direction with no gap, each a small colour step from the last, now
becomes one object filled with a linear gradient through the strips'
colours (stops on a straight colour ramp dropped), and the clip path
itself when it was the clip's only art. Abutting blocks of distinct
colours stay apart.
The reader gives an Xy right after a compound path or a text object to
that object. The writer now writes XR before the Xy of type, images and
guides, so type next to type, a compound path before type, image or
guide, and type before an image or guide keep their own opacity, blend
mode and knockout shape flag.
- Type keeps its Isolate Blending and Knockout Group state in a state
block after its text object, as its outlines did on their group.
- The reader no longer gives a layer the Xy before its last text object.
- The ASCII85 end marker of the text document stays on one line.
- The warning and docs/file-format-parity.md also list area type in an
open frame, type on an open path whose ends meet, type of only white
space and threads of type on a path as written as outlines.
- README.md, ROADMAP.md, docs/gaps.md, docs/roadmap.md and
docs/target-app-parity.md describe the editing copy a saved .ai holds.
- clip_path's doc comment is back on clip_path.
- import_fuzz reaches threaded area type and vertical type.
The editing copy of a PDF-compatible .ai wrote every text object as its
outlines. Point type, area type and type on a path are now written as
text: a text object in the layers that names its story, and the text
document after the document data (%AI11_BeginTextDocument) holding the
stories.
- Each story holds its characters (a paragraph ends in \r, a forced line
break is \x03), its character runs (font, size, leading, tracking,
baseline shift, horizontal and vertical scale, solid fill and stroke
with its weight, capitals, Tate-chu-yoko) and its paragraph runs
(alignment, indents, space before and after, hyphenation, right-to-left
direction).
- Point type keeps its point and, when it is turned, its matrix. Type
scaled by one factor, such as all type on a large canvas, has its scale
in its sizes, frame and path. Area type keeps its frame, rows,
columns, gutters and first baseline, type on a path its path and where
it starts and ends, and vertical type its orientation. A threaded story
is one story through its frames in order. Area type and type on a path
carry their frame's path in the layers as well.
- Type the text document can't hold is written as its outlines, with a
warning: type in opacity masks, pattern tiles and art cut to a clipping
object, mirrored type, turned or unevenly scaled area type and type on
a path, frames of several parts, area type that flows around a text wrap,
threads whose frames differ in orientation or include a frame written
as outlines, type and stories past the sizes the reader reads, and type
with inline graphics, ruby, gradient or pattern paint or an appearance
or opacity mask of its own. Other character and paragraph attributes are left out, with
a warning.
Tracking is written as a whole number of thousandths of an em, and
solid paints as simple paints; tracking that isn't a whole number is
rounded, with the warning.
Each construct is written in the form VectorCraft's .ai reader reads
(crates/eps/src/import/ate.rs at 36ef34dfdd: Texts::read :407, story
:501, frame :456, para :562, style :588, paint :622, AreaFrame::read
:284; the text object in import/ai/read/art.rs:15 and its path in
import/ai/frames.rs:26), and the tests read the written data back
through that reader. The scripting
reference documents the same attributes on the reading side (text frame
kinds, columnCount, columnGutter, rowCount, startTValue, endTValue,
orientation, and the character attributes):
https://web.archive.org/web/20160410101607/https://wwwimages.adobe.com/content/dam/Adobe/en/devnet/illustrator/sdk/CC2014/Illustrator%20Scripting%20Reference%20-%20JavaScript.pdf
The reader now closes a text object's frame path painted with a closing
operator (n, f, s, b, h), so area type's frame comes back closed; places
point type whose story keeps no composed lines at its frame's point;
keeps a story's last empty paragraph (only the \r that ends the story is
dropped); gives type made from the text document its text object's lock,
as it gives it its visibility; and gives type its text object's knockout
shape flag, as it gives it its opacity and blend mode.
Tests: the round trip of every kind of type and its state, a second
write of what is read back giving the same bytes, the text document and
stubs, scaled point type, a story split between threaded frames, the
fallbacks and the warnings, and the engine's editing copy with every save
option; a fuzz case for damaged text documents and stubs.
Docs: docs/file-format-parity.md.
a_pan_moves_the_marks_without_building_them covered Direct Selection
only. It now runs with both tools.
The module comment and MAX_PAN's comment now say what is kept as
triangles and as document points, and when a pan builds the marks again.
A test label now says points rather than px.
The timings in docs/target-app-parity.md are measured again with 10 fill
colors on the 2,000 circles. The pixel sentence there also names the
rounding errors of kept vertices.
The progress line gives the release-build timings of the head that tests each subpath and handle against the view, and says which corner can differ after a pan.
The canvas flattened every selected object's outline and tessellated its
anchors and handles again in each frame. It now keeps them per object as
one mesh, valid for the object's node, layer color and selected anchors.
An idle frame draws the mesh again. A pan moves kept outlines and handles
and places the anchor squares again.
A frame with a new zoom, rotation or display scale draws plain shapes and
keeps nothing, and the next frame at that view builds the marks. Entries
of objects that leave the selection or the document are dropped.
With ribs only at the path's corners (an Along gradient), the ribs that reach
across an arrowhead stopped at the last corner inside its reach, so the slice
narrowed from the head's tip towards the next corner and left the corners of
a Triangle head's base outside every slice. Where each arrowhead's reach ends
now gets a rib of its own.
When a frame threaded in before the edited frame takes all of the story's
text, the edited frame is left with no text while the story stays
selected. The other frames' text is now highlighted, Delete and Backspace
replace the story, an Alt+arrow step changes the tracking of every frame,
and Copy and Cut take the story. A story whose frames hold no text has
nothing to copy, and Delete in it records no undo step.
With a whole story selected, the highlight and typing read the frames saved
at Select All, while a pick, a fill and the other story-wide edits read the
document's thread. A frame added by text.thread.add took a pick without being
highlighted, and typing left its text in place.
Both now read the thread through Document::story_of. A frame threaded in
during the selection is highlighted and takes the edit, and a frame that
leaves the thread is not highlighted and keeps its text.
appearance.copyFrom and a fill or stroke change on a story selected by
Select All no longer skip locked frames, hidden frames and frames on a
locked artboard. They apply to every frame of the story, as the Character
panel's story edits do. appearance.copyFrom still leaves out a frame that
is its source.