Commit Graph
8904 Commits
Author SHA1 Message Date
dotCooCoo 40a46e539d Type: story-wide panel changes follow the story's current thread
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.
2026-11-07 09:17:46 +07:00
BFlat 845306373b Merge pull request #6017 from dotCooCoo/fix/ai-drawn-look-count
.ai import: drawn looks in pattern and brush art count in the note
2026-11-07 10:15:26 +08:00
BFlat 936f6034da Merge pull request #6014 from mockydevs/fix/ai-import-eid-heading
EPS/.ai editing data: a transparency set inside a clipping group stays after it
2026-11-07 10:15:10 +08:00
BFlat 7e3601d11c Merge pull request #6011 from mockydevs/fix/ai-import-blend-straight-spine
EPS/.ai editing data: blends with no spine written come in live
2026-11-07 10:14:54 +08:00
BFlat 7db6d41ec0 Merge pull request #5992 from mockydevs/fix/ai-symbols-before-art-styles
EPS/.ai editing data: symbols defined before the art styles take them
2026-11-07 10:14:38 +08:00
dotCooCoo 0d91749c74 .ai import: drawn looks in pattern and brush art count in the note
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.
2026-11-07 09:00:23 +07:00
Don Omondi ed00a8870e EPS/.ai editing data: a transparency set inside a clipping group stays after it
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.
2026-11-07 09:00:20 +07:00
Don Omondi 95ac8d7cc7 EPS/.ai editing data: blends with no spine written come in live
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.
2026-11-07 09:00:15 +07:00
Don Omondi 2626791d7d EPS/.ai editing data: symbols defined before the art styles take them
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.
2026-11-07 08:59:55 +07:00
BFlat d2b82d6b32 Merge pull request #6005 from dotCooCoo/fix/prefs-set-folder-check
Preferences: prefs.set refuses a missing or unusable recovery or plug-ins folder
2026-11-07 09:57:12 +08:00
BFlat 4802247106 Merge pull request #6004 from dotCooCoo/fix/dialog-enter-repeat
Dialogs: a held Enter or Escape stops at the dialog it opened or closed
2026-11-07 09:56:52 +08:00
BFlat 0864d63ee2 Merge pull request #5988 from dotCooCoo/fix/offset-contour-check-index
Offset Path: the spurious-contour check tests only the source segments near each contour
2026-11-07 09:56:37 +08:00
BFlat 3637aebc5f Merge pull request #5983 from dotCooCoo/feat/artboard-context-menu
Artboards: the Artboard tool's canvas menu cuts, copies, pastes, renames, rearranges and exports artboards
2026-11-07 09:56:22 +08:00
dotCooCoo 9b9803aa0f Tests: the unusable-folder prefs test restores folder modes when it fails
set_refuses_a_recovery_or_plugins_folder_it_cannot_use takes write or
list permission away from two folders. A guard now gives each folder mode
0o755 when it is dropped, also when an assertion panics, so the test
folder is removed afterwards.
2026-11-07 08:38:20 +07:00
dotCooCoo 104d9562d4 Preferences: prefs.set refuses a missing or unusable recovery or plug-ins folder
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.
2026-11-07 08:38:20 +07:00
dotCooCoo 20f35e4655 Dialogs: a held Enter or Escape stops at the dialog it opened or closed
Enter and Escape counted their key repeats as presses. Holding Enter with
a selection and a selection tool opened the Move dialog, confirmed it,
and opened it again at the key's repeat rate. After a drag, which gives
Move an offset, each round moved the object again.

The app now records what Enter or Escape went down on: the open dialog,
the command search, Edit Toolbar's drawer or Presentation Mode. When that
changes, the key's presses are removed from the input until it is let go.
The tool keys, the dialog's OK and the dialog's Escape also ignore
repeats, so holding Escape with the place cursor loaded discards one file.
A new press still acts, and Enter held in the Type tool still repeats line
breaks.

This also fixes these related faults:
- Ctrl+Enter or Cmd+Enter opened Move and confirmed it in the same frame.
- Holding the Enter that confirmed a dialog typed line breaks into the
  text being edited.
- A command bound to Enter reopened its dialog after the dialog's OK.
- Holding Enter on a value a field rejected confirmed the dialog.
- A command search that opened while Enter was down ran its first result.
- Holding Escape over a dialog's Tips closed the dialog as well.
- Holding Escape over a dialog went on to close Edit Toolbar's drawer,
  leave isolation mode or run a command bound to Escape.
2026-11-07 08:38:15 +07:00
dotCooCoo 2e8e8a1909 Offset Path: the spurious-contour check tests only the source segments near each contour
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.
2026-11-07 08:38:12 +07:00
dotCooCoo c7c8e5428d Artboards: the Artboard tool's canvas menu cuts, copies, pastes, renames, rearranges and exports artboards
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.
2026-11-07 08:37:44 +07:00
BFlat 2908e6f9f8 Merge pull request #6008 from dotCooCoo/fix/trace-logo-fit-cap
Image Trace: the logo fitter keeps no piece over its tolerance
2026-11-07 09:36:04 +08:00
BFlat 389e6faf7a Merge pull request #6003 from mockydevs/fix/eps-huge-image-skips-data
EPS import: an image too large to read skips its data instead of failing the file
2026-11-07 09:35:49 +08:00
BFlat baab0eadbe Merge pull request #6002 from mockydevs/fix/eps-cvi-radix
EPS import: cvi and cvr read radix numbers (eps2write spot colours with spaces)
2026-11-07 09:35:34 +08:00
BFlat cddf45801e Merge pull request #6001 from mockydevs/fix/eps-subfile-long-count
EPS import: SubFileDecode reads counts past 4 MiB (eps2write files with long streams open)
2026-11-07 09:35:19 +08:00
BFlat b207e3f7a9 Merge pull request #6000 from mockydevs/fix/eps-bind-readonly-procs
EPS import: bind leaves the procedures it already bound alone (Ghostscript eps2write files open)
2026-11-07 09:35:04 +08:00
BFlat fde645e32e Merge pull request #5993 from dotCooCoo/fix/mcp-save-warning-labels
Save: notes on unread save options name the legacy or non-PDF-compatible .ai, in every save command
2026-11-07 09:34:47 +08:00
BFlat c38f1cc1ee Merge pull request #5990 from dotCooCoo/fix/ai-mask-lone-object
.ai import: opacity mask art of one object opens as that object
2026-11-07 09:34:37 +08:00
BFlat 6cf98654f6 Merge pull request #5989 from dotCooCoo/fix/pdf-password-docs
Docs: PDF password export says when the file ID and the bytes vary
2026-11-07 09:34:22 +08:00
BFlat 4dbc16acf8 Merge pull request #5986 from dotCooCoo/fix/artboards-menu-new-active
Artboards: the panel menu's New Artboard makes the new artboard active
2026-11-07 09:34:06 +08:00
dotCooCoo 2facf55c29 Image Trace: the logo fitter keeps no piece over its tolerance
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.
2026-11-07 08:19:44 +07:00
Don Omondi dfa9548938 EPS import: an image too large to read skips its data
An image over the pixel cap was left out without reading its data, so
the program went on to read that data as PostScript and the file failed
to open (Ghostscript's eps2write writes a page with a large inline image
this way). The data is now skipped: the filters that find their own end
(ASCIIHexDecode, ASCII85Decode, SubFileDecode) read the file up to it,
without decoding what they pass.
2026-11-07 08:19:40 +07:00
Don Omondi fdbd116577 EPS import: cvi and cvr read radix numbers
cvi and cvr read a string as the PostScript syntax reads a number
(PLRM 3rd ed., cvi, cvr), so (16#20) cvi is 32. The reader parsed strings
as decimal only. Ghostscript's eps2write prolog undoes a name's #20 escape
that way, so its files with a spot colour named with spaces stopped
reading at that colour.
2026-11-07 08:19:36 +07:00
Don Omondi 8c57a65ee0 EPS import: SubFileDecode reads counts past the allocation cap
The count of a SubFileDecode filter bounds what it passes through, not
what it allocates, but the reader refused counts over 4 MiB as a
rangecheck. Ghostscript's eps2write files read each content stream with
currentfile Length () /SubFileDecode filter, so a page whose stream is
longer than 4 MiB failed to open.
2026-11-07 08:19:33 +07:00
Don Omondi 06a035e86b EPS import: bind leaves the procedures it already bound alone
bind makes each procedure it goes into read-only and ignores read-only
procedures (PLRM 3rd ed., bind). The reader bound them again, so a prolog
that binds a procedure holding an earlier-bound one, after defining a name
such as M as an operator, turned that procedure's own variable M into
setmiterlimit. Ghostscript's eps2write prolog does this, and its files with
sampled functions (transfer, black generation) failed to open.
2026-11-07 08:19:29 +07:00
dotCooCoo 1e2ff653b5 Save: the save commands' params text names the notes on options
document.save's params text, which file.saveAs, file.saveCopy and
file.saveAsTemplate share, now says that the warnings also name each key
given in `options` that the format doesn't read.
2026-11-07 08:19:25 +07:00
dotCooCoo 7ee6b429ba MCP: save_file notes name the legacy or non-PDF-compatible .ai
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.
2026-11-07 08:19:24 +07:00
dotCooCoo 3d7dda200e .ai import: opacity mask art of one object opens as that object
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.
2026-11-07 08:19:20 +07:00
dotCooCoo ad5ef55b30 Docs: PDF password export says when the file ID and the bytes vary
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.
2026-11-07 08:19:16 +07:00
dotCooCoo f4576de615 Artboards: the panel menu's New Artboard makes the new artboard active
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.
2026-11-07 08:19:12 +07:00
BFlat 9592b6a5ca Merge pull request #5982 from dotCooCoo/fix/link-watch-worker-gone
Links: a link check whose worker ends without a result no longer stops later checks
2026-11-07 09:11:28 +08:00
BFlat 60f1bff1d8 Merge pull request #5978 from dotCooCoo/fix/ai-image-knockout-shape
.ai import: images, meshes, blends and styled objects keep the knockout shape flag
2026-11-07 09:11:07 +08:00
BFlat d0d915a721 Merge pull request #5977 from kylekanouse/fix/svg-textpath-anchor
SVG: centred and right-aligned type on a path keeps its place
2026-11-07 09:10:51 +08:00
BFlat 4e16340f2c Merge pull request #5946 from ruchirguitar/fix/4947-indic-hyphenation
Add hyphenation for eleven Indian languages
2026-11-07 09:10:37 +08:00
BFlat 4b29225c30 Merge pull request #5965 from dotCooCoo/feat/ai-editing-data-s5
.ai save: the editing copy keeps type as type
2026-11-07 09:10:24 +08:00
BFlat 51aea90f07 Merge pull request #5972 from dotCooCoo/fix/selection-overlay-per-frame
Canvas: selection outlines and anchors are reused between frames
2026-11-07 09:10:03 +08:00
BFlat afdc490d3a Merge pull request #5971 from slafebre/fix/5964-gradient-dash-corner
Part of #5964: stroke gradients cover an arrowhead to the end of its reach
2026-11-07 09:09:47 +08:00
BFlat 073923ee30 Merge pull request #5969 from dotCooCoo/fix/eyedropper-keeps-story-selection
Type: switching to the Eyedropper keeps a whole-story selection
2026-11-07 09:09:33 +08:00
BFlat 085bbf5495 Merge pull request #5968 from slafebre/fix/5714-smooth-width-profiles
Fix #5714: widths run smoothly between width points
2026-11-07 09:09:19 +08:00
BFlat ee4f711fbe Merge pull request #5967 from dotCooCoo/fix/ai-brushed-paths
.ai import: paths with an Art brush open with the brush on their stroke
2026-11-07 09:09:01 +08:00
BFlat 7adc7fa40c Merge pull request #5966 from dotCooCoo/fix/ai-envelope-stroked-box
.ai import: envelopes map from their stroked box when the file saves its size
2026-11-07 09:08:45 +08:00
BFlat 9950bde2e7 Merge pull request #5963 from dotCooCoo/fix/pdf-export-cost
PDF export: members of a plain group or layer are measured once to leave out off-page art, and the link walk measures only what it reads
2026-11-07 09:08:28 +08:00
BFlat e940a55cb6 Merge pull request #5959 from dotCooCoo/fix/ai-symbol-section-strings
.ai import: ASCII85 data in a section does not hide the section's end
2026-11-07 09:08:13 +08:00