Commit Graph
5312 Commits
Author SHA1 Message Date
dotCooCoo 86e085f73d Control bar: a narrow bar keeps the Transform link
With something selected, the Fill and Stroke, Opacity, Graphic Style and
Character controls now show only while the Transform link and the
separator ahead of it still have room after them, the way the Paragraph,
vertical alignment and Align groups keep the link's room. A narrow bar
leaves those controls out first and keeps the link, instead of leaving
out the link.

- The Character controls show whole or not at all. While they are left
  out, the Paragraph, vertical alignment and Align controls after them
  are left out too, so a wider bar never drops a group that a narrower
  one showed.
- The room checks for the width profile, Recolor Artwork and Global Edit
  Options count the spacing after each control.

Tests: the_control_bar_s_controls_stay_inside_the_bar_in_a_narrow_window
now also checks selected type.
2026-11-13 19:04:05 -08:00
dotCooCoo 751b50bf58 i18n: messages keep bracketed field names and accepted values in English
49 status and error messages in the Hindi, Bulgarian, Danish,
Indonesian, Dutch, Brazilian Portuguese, Swedish and Turkish catalogs
translated the field names in brackets, such as `[subpath, anchor]` or
`[start, end]`, which the parameter documentation spells in English, or
the values an `unknown` or `bad model` message lists, such as
`(points, lines)` or `(left|right|top|bottom)`. Commands match those
values against the English words, so a user who passed the translated
value got the same error again. These rows now keep the English names
and values and translate the rest of the sentence.

A new test, translated_messages_keep_the_field_names_and_values_their_english_lists,
checks every catalog for bracketed field lists, `a|b|c` value lists and
the values listed in parentheses after `unknown` and `bad model`.
2026-11-13 19:01:48 -08:00
dotCooCoo 87c8def043 .ai save: a linked image with a Warp keeps its live Warp and its link
A linked image whose appearance is one Warp effect, with no opacity mask,
was saved to the .ai editing data as its drawn art, so its live Warp was
lost. It is now written with an art style of that Warp, as an embedded
image is: its bent pieces are its drawn look, and the image itself
follows on %_ lines as a placed file with its path, its folder relative
to the document's and its preview. In an opacity mask's art the copy is
embedded, with the existing warning for linked images in masks.

Opening such a file reads the image back linked, with its Warp live.
A hidden image with a Warp, embedded or linked, is now compared with its
drawn look shown, so it keeps its Warp too; before, the look drew
nothing and the image came in as its drawn pieces.
2026-11-13 18:51:03 -08:00
dotCooCoo fecf724501 Smart Guides: Parametric Shape and Slice tools snap as the drawing tools do
The Parametric Shape tool's center and the Slice tool's corners snapped
with Smart Guides to the bounds of the art only, so View › Snap to Glyph
had no effect on them, and neither did the anchors and segments of
paths that the other drawing tools snap to. The point dragged out from a
Parametric Shape's center did not snap at all, and neither tool showed
Smart Guides while hovering before a press.

Both tools now snap through the drawing tools' shared snapping
(DrawSnap). A Parametric Shape's center (from a drag or a double-click),
the point dragged out from it, and a slice's corners land on glyph
guides and on path anchors and segments. The guides show while hovering
and during the drag. When a ruler guide then takes a slice corner, the
Smart Guides are no longer shown. A click with the Parametric Shape tool
still draws nothing when its center snaps a few pixels from the pointer.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 18:50:03 -08:00
dotCooCoo 59084a3aab Merge main into fix/recovery-keeps-open-notes 2026-11-13 18:48:54 -08:00
dotCooCoo 01de2a14cf Recovery: restoring documents keeps their linked-file lines and warnings
After Restore in the dialog Data Recovery shows at launch, the status
bar wrote the restore count over the line about the restored document's
linked files, and the warnings each copy restored with were never shown.

The status bar now shows the count followed by the first of the
restored documents' notes: each document's lines about its linked
files, then its warnings, what reading the copy left out first, named
with the document's title when more than one was restored. Hovering
the message lists them all. The count is the number of documents
restored.

The questions about each restored document's missing or modified
linked files now come one document at a time, with that document made
the current one, so a later document's question no longer replaces an
earlier one's. When a copy can't be restored, the status bar shows the
error and its hover keeps the count and the restored documents' notes.
2026-11-13 18:47:55 -08:00
dotCooCoo ffd9579ccb Merge main into fix/mcp-docs-stack-file 2026-11-13 18:37:26 -08:00
dotCooCoo 0104aaeb9d Docs: script stack frames and $.fileName name the file of the code
docs/mcp.md's line and stack row said $.stack shows at most 64 lines
and uses [global] only for the script's own code. It keeps the
innermost 64 frames after a leading line "…" when some are left out,
and [global] names any code outside a function, including code that
an included file, $.evalFile or eval runs. The row now also says how
a frame's file compares with $.fileName in each case: the same file
for code from a file, the run's name where $.fileName is empty for a
script given as source, [eval] where $.fileName is the file being run,
and [unknown] at line 0 where $.fileName is empty.

The engineName row now gives the #targetengine name, and the
script.run params text, the script module doc and the Scripts evidence
line say $.fileName is the file of the code that reads it rather than
the file being run.
2026-11-13 18:36:47 -08:00
dotCooCoo a4a570323e Merge main into fix/3d-export-builds-once 2026-11-13 18:36:39 -08:00
dotCooCoo 3d9a461be5 3D: Export 3D Object builds each Extrude and Inflate solid once
Export 3D Object built every Extrude & Bevel (both kinds) and Inflate
solid twice: once for the facets that decide whether the art draws it and
count toward the object's face limit, and again for its mesh.

The solid builder now keeps the projected facets and the faces before
projection from one pass (`extrude_meshed`, `inflate_meshed`), and the
export decides and meshes each part from that one build. Where a mesh
built alone cuts Inflate's twisted sides differently (it has less room
left after keeping the faces turned away), the mesh's sides are cut with
its own room. Strokes past their limits are still left out, a fill's
error and the object's face limit still stop the export at the same
part, and the triangle budget is unchanged.

Tests compare the facets and meshes with separately built ones bit for
bit, and count one build per solid.
2026-11-13 18:35:48 -08:00
BFlat 446bf59bc2 Merge pull request #7265 from dotCooCoo/feat/live-paint-cursor-swatch-preview
Live Paint Bucket: Cursor Swatch Preview and arrow keys pick swatches
2026-11-14 09:33:39 +07:00
BFlat 02dd94e9b8 Merge pull request #7347 from dotCooCoo/fix/corner-set-member-keys
Path Precision Tools: Corner commands refuse unknown item keys
2026-11-14 09:33:31 +07:00
BFlat e026414c70 Merge pull request #7348 from dotCooCoo/fix/csv-utf16-no-bom
Variables: Import Data Sets reads UTF-16 CSV files without a byte-order mark
2026-11-14 09:33:23 +07:00
BFlat caa56c2739 Merge pull request #7334 from dotCooCoo/fix/wrap-offset-length-field
Text Wrap: Offset is a distance in the document's units
2026-11-14 09:33:15 +07:00
BFlat af8907ce8c Merge pull request #7356 from dotCooCoo/fix/pl-message-rows
i18n: Polish has a row for 1,808 of the messages the untranslated report lists
2026-11-14 09:33:07 +07:00
BFlat 700089f819 Merge pull request #7343 from dotCooCoo/fix/uk-message-rows
i18n: Ukrainian translates 1,811 more status and error messages
2026-11-14 09:32:59 +07:00
BFlat ea24f694cf Merge pull request #7345 from dotCooCoo/fix/ai-twist-straight-guide-reach
.ai import: straight compound paths whose guides reach past them keep the drawn look under Twist
2026-11-14 09:32:51 +07:00
BFlat 826c8647ec Merge pull request #7361 from dotCooCoo/fix/zh-hans-message-rows
i18n: Simplified Chinese has a row for 1,813 of the messages the untranslated report lists
2026-11-14 09:32:43 +07:00
dotCooCoo 70387fd0ae Type: Character and Paragraph panel changes apply to every frame of a selected story
With the Selection tool, a change in the Character or Paragraph panel to a
selected frame of threaded text now changes every frame of its story,
locked and hidden frames included, in one undo step. Before, only the
selected frames changed.

- The panels send the frames of each selected story as the command's ids:
  every Character and Paragraph field, the font family menu and its
  preview, Bullets and Numbers, anti-aliasing, Variable Font axes, Reset
  Panel in both panels, the Tate-chu-yoko, Warichu and Hyphenation
  dialogs, and the Tabs panel's stops and Clear All Tabs. A story
  selected through several frames or a group is listed once.
- The fields read every frame of the story and show a value only when all
  frames share it.
- Clear All Tabs is enabled when another frame of the story has stops.
- Convert to Text keeps acting on the selected frames.
2026-11-13 18:31:04 -08:00
dotCooCoo ea72fe89f5 Merge main into fix/control-bar-narrow-fill-stroke 2026-11-13 18:28:05 -08:00
dotCooCoo 719e3450b2 .ai import and save: Art brushes keep None, their width, scale and flips
A .ai path with an Art brush opened with the brush on its stroke only
when the brush stretched its art at 100% in Tints, unflipped. Paths with
an Art brush in None, at another fixed width, with Stretch Between
Guides, or flipped along or across now open as the path with the brush
on its stroke too, and the brush in the Brushes panel has those options.
The guides come in as fractions of the art, from the lengths of the art
outside them. A brush with Scale Proportionately comes into the panel
with that option, and its paths keep their drawn look.

Paths keep their drawn look when their settings that change the drawing
differ from the brush's, and when the brush is in Tints and Shades or
Hue Shift, has a width that follows the pen, has guides that leave no
art between them, or has a Spacing, Adjustment or FoldAdjustment other
than 0, 1 and 1.

The .ai save writes the same options, so such brushes and the paths
that use them come back as they were; a path with a proportional brush
is written as its brush's art.
2026-11-13 18:27:54 -08:00
ruchirguitarandruchirguitar 30eb14d7dc PDF import: outlined Indic glyphs keep their own stroke and transparency (#5235) (#6957)
* PDF import: outlined Indic glyphs keep their own stroke and transparency (#5235)

Follow-up to #6906, for two review findings on how a line kept as
outlines is joined into paths:

- Glyphs were joined when their stroke widths matched; dash, cap, join
  and miter limit were ignored, so a dashed glyph took the stroke of the
  solid one before it. They join only when the whole stroke matches.
- Translucent glyphs were joined into one fill, where overlapping marks
  paint once instead of compositing as the file draws them. Only opaque
  glyphs join.

Also records the fix in the PDF row of docs/target-app-parity.md and in
docs/roadmap.md, as AGENTS.md asks.

Tests: outlined_glyphs_stroked_differently_stay_apart and
outlined_translucent_glyphs_stay_apart (both fail without the change).

* PDF import: outlined Indic glyphs under a soft mask stay apart; check kept geometry (#5235)

Review follow-ups on #6957 and #6906:

- Glyphs kept as outlines under a soft mask were joined into one path,
  so the mask was applied once to all of them where the file applies it
  to each glyph. They now join only when no soft mask is active.
- The fallback tests counted outline nodes only. A new test compares the
  kept outlines (element count and bounding box) with the same file
  opened as outlines, so a dropped or moved glyph fails it.

Tests: outlined_glyphs_under_a_soft_mask_stay_apart (fails without the
change) and kept_glyphs_are_where_the_file_draws_them.

* PDF import: mask outlined Indic glyphs one by one under a soft mask (#5235)

Review follow-up on #6957. Keeping glyphs out of one shared path was not
enough: each path still went into the soft mask's queue and
flush_masked wrapped them all in one masked group, so a mask that is not
constant was applied once to every glyph, where overlapping glyphs
composite one by one in the file.

With a soft mask active the queued art is now drained before the first
glyph and after each one, so every glyph gets a mask of its own.

Test: outlined_glyphs_under_a_varying_soft_mask_are_masked_one_by_one
checks that each outlined glyph carries its own mask (0 of 3 without
the change).

* #6957: clarify soft-mask exception in glyph grouping docs

---------

Co-authored-by: ruchirguitar <info@jeevantirth.org>
2026-11-14 03:26:20 +01:00
dotCooCoo 20fc6a0225 Symbols: Break Link and Expand keep an instance's bounding box
After Reset Bounding Box on a turned symbol instance, Break Link to
Symbol and Object > Expand gave the art a box turned with the instance's
transform again. The art's boxes now turn with the instance's own box,
so they stand square when the instance's box did, and the angles the
art has inside the symbol are kept relative to it. The group that an
instance's opacity, blending mode or opacity mask adds around the art
takes the instance's box angle instead of standing square to the page.

A reflected instance can hold a box 180 degrees from the box its
transform gives in one step; the art now takes the instance's box
there too, the same rectangle with its handles where the instance had
them.

Compound shapes and Pathfinder receive an instance's art through the
same rule.

The clip groups and clip paths that 9-slice guides make for gradient
and pattern art take the angle of the cell that places them, and the
outer group keeps the object's angle turned by the instance, instead
of standing square to the page. This also changes the result for an
instance that was never reset: a 20 degree sliced instance gave clip
groups at 0 degrees and now gives them at 20.

Docs: params text, docs/mcp.md, docs/target-app-parity.md.
2026-11-13 18:26:00 -08:00
dotCooCoo 6551b28b44 Control bar: in a narrow window, Fill, Stroke and Opacity stay inside the bar
Short of room, the Control bar drew the Fill and Stroke chips, the Stroke
link and weight field, the width profile, the Opacity field and the Graphic
Style controls past the panel menu button. Docked, the bar then left the
panel menu out; floating, it cut a control in half.

- Each of those controls now shows only while the bar has room for all of
  it. The bar draws them from left to right, each only when the room left
  still holds it, so the Opacity link and field can still show after a
  Stroke link and weight field that did not fit.
- The Snapping menu, the selection's label, the Convert and Anchors groups,
  the isolation button, Document Setup and Preferences show only while
  they fit, and a group separator only while it has room.

Test: the_control_bar_s_controls_stay_inside_the_bar_in_a_narrow_window
checks widths from 150 to 1500 points, docked top and bottom and floating.
2026-11-13 18:21:52 -08:00
ncic b0772bc2d6 Merge upstream main into pencil-alt-close-straight 2026-11-14 03:16:34 +01:00
dotCooCoo ab0d8b6d77 Home: a Learn section lists the tutorials and the Quick skill guide
The Home screen gets a Learn section between Recent Files and the new-file
presets: the Quick skill guide card, which shows the Learn panel's list of
skills (learn.skills), and each tutorial under its skill, which shows the
panel at its steps (learn.show). It works with no document open and over
open documents, opens no document and never hides the panel.

The card is shared with the panel's For you tab and now shows an outline
while it has the keyboard focus.
2026-11-13 18:13:45 -08:00
dotCooCoo c8bdb6ee06 Merge main into fix/int-param-wrong-type 2026-11-13 18:03:25 -08:00
dotCooCoo 78ce56d021 MCP: an integer given as a string or a fraction is refused as the wrong type, not reported as missing
A command that needs a whole number of 0 or more, such as `index` of
`appearance.setItem`, `anchor` of `path.removeAnchor` and
`addon.pen.removePoint`, `sourceDocument` of `edit.dropSelection`, `index`
of `document.activate` and `to` of `document.move`, answered "missing
integer `index`" (or "missing index") both when the key was left out and
when it was given as a value that is not a whole number of 0 or more, such
as "3", 2.5, -1 or true. A value that is given but is not one is now
refused with "`index` must be a whole number", the message object ids
already use. A key left out or given as null is still missing, and an
optional index such as `subpath` keeps its default. Neither error changes
the document or records an undo step.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 18:02:42 -08:00
dotCooCoo 7b475b46b0 .ai import: Calligraphic paths with pen samples keep their drawn look
A path's own lines can be followed by samples of the pen
(`(…) Xt n XD`). The reader took them as the end of the object, so the
style marker after them was not matched: the path came in as its drawn
look plus a second, unpainted copy of the path, and no note said the
look was kept. The samples now stay with the path. They aren't read,
so a path that has them keeps its drawn look alone, with the note, when
a setting of its Calligraphic brush varies with the pen (Pressure,
Tilt, Bearing or Rotation, with a variation above 0). With any other
style, an Art brush or a Calligraphic brush that doesn't follow the
pen included, it takes the style as it would without them.

A Calligraphic brush's filter with an entry the reader doesn't know, or
with a variable width, keeps the drawn look too, as an Art brush's
filter does.

Docs: docs/file-format-parity.md, docs/gaps.md.
2026-11-13 17:59:50 -08:00
dotCooCoo 1e4b6c4e22 Merge main into fix/ai-hidden-ruler-guide 2026-11-13 17:56:13 -08:00
dotCooCoo cfa76d674f .ai import: hidden ruler guides open as ruler guides with their own state
A straight `(N) *` guide path that runs across the canvas or an artboard
opens as a ruler guide, but a hidden one (`1 Xw`) stayed a guide path.
It now opens as a ruler guide too, and every ruler guide made from such a
path keeps the path's hide, lock and name, so its Layers row shows them.
Before, a locked guide opened unlocked and a named one lost its name.

Hidden or locked guide paths that are short, slanted, grouped or `(S) *`
stay guide paths, and commented copies (`%_`) are still left out.

Docs: docs/target-app-parity.md, docs/file-format-parity.md.
2026-11-13 17:55:31 -08:00
dotCooCoo b3fae432b6 Merge main into fix/batch-swatch-default-paint 2026-11-13 17:54:08 -08:00
dotCooCoo 73fd610324 Swatches: swatch steps in a batch change the paints for new art
A swatch delete, Swatch Options edit, merge, Edit Color Group, Spot
Colors options change or Default Swatches replace run as a
command.batch step left the fill and stroke new art takes linked to the
old or deleted swatch, because the defaults were skipped whenever an
interaction was open. A batch step now rewrites them as the command run
on its own does; a live Swatch Options preview still leaves them alone,
and a failed batch or a canceled batch preview puts them back.

The same commands now also rewrite the fills and strokes of the
appearance new art takes, and record the change with their undo step,
so Undo and Redo put the paints for new art back with the swatches.
2026-11-13 17:54:07 -08:00
BFlat 9fcfc81cc2 Merge pull request #7336 from dotCooCoo/fix/i18n-scan-gaps
i18n: the untranslated report checks the effects, map_err messages and schema phrases
2026-11-14 08:40:23 +07:00
BFlat c1efdbdaae Merge pull request #7255 from dotCooCoo/fix/folder-prefs-out-of-recorded-steps
Actions: keep folder preferences out of saved sets and confined replies
2026-11-14 08:40:15 +07:00
BFlat 5ccb284e34 Merge pull request #7335 from dotCooCoo/fix/live-paint-noop-undo
Live Paint: an edit that changes nothing records no undo step
2026-11-14 08:40:06 +07:00
BFlat bf3cf422e2 Merge pull request #7311 from dotCooCoo/fix/ai-graphs-keep-data
PDF/.ai import: graphs keep their data and settings when their records read whole
2026-11-14 08:39:57 +07:00
BFlat 99011cba0c Merge pull request #7288 from dotCooCoo/fix/task-bar-wraps-on-narrow-canvas
Contextual Task Bar: actions wrap onto more rows on a narrow canvas
2026-11-14 08:39:49 +07:00
BFlat 12117a48f9 Merge pull request #7324 from dotCooCoo/fix/edit-colors-no-change-undo
Edit Colors: no undo step when a recolor changes nothing
2026-11-14 08:39:40 +07:00
BFlat b0a2dfd448 Merge pull request #7309 from dotCooCoo/fix/de-message-rows
i18n: German has a row for 1,804 of the messages the untranslated report lists
2026-11-14 08:39:21 +07:00
BFlat 83ed754450 Merge pull request #7326 from dotCooCoo/fix/trace-jpeg-blocks
Image Trace: a JPEG's 8 x 8 blocks no longer trace as staircase steps
2026-11-14 08:39:13 +07:00
BFlat 6cc5dca69e Merge pull request #7315 from dotCooCoo/fix/it-message-rows
i18n: Italian translates 1,802 more status and error messages
2026-11-14 08:39:04 +07:00
BFlat c028cf6ab1 Merge pull request #7332 from dotCooCoo/fix/type-outlines-keep-appearance
Type: Create Outlines keeps the type object's own fills and strokes
2026-11-14 08:38:56 +07:00
BFlat e69fb10ff3 Merge pull request #7341 from dotCooCoo/fix/pt-br-message-rows
i18n: Brazilian Portuguese translates 1,812 of the status and error messages the untranslated report lists
2026-11-14 08:38:47 +07:00
BFlat 043e008194 Merge pull request #7196 from dotCooCoo/fix/item-4459
Brushes: strokes draw with the first of two brushes with one name
2026-11-14 08:38:40 +07:00
BFlat f336609146 Merge pull request #7339 from dotCooCoo/docs/linux-title-bar-frame
Docs: the Linux title bar paragraphs describe the frame the desktop draws
2026-11-14 08:38:32 +07:00
dotCooCoo 91f77f1eb8 Actions: Button Mode shows actions as colored buttons that play on a click
The Actions panel menu has a Button Mode item with a check mark. While it
is on, the panel shows every action of every set by name as a button in
its Action Options color, without set names, steps or checkmarks, and a
click on a button plays that action without its excluded steps. Choosing
Button Mode again shows the list.

- ui.action.buttonMode {enabled?} switches the view (left out: the
  other view) and is kept with the UI preferences; it cannot be turned
  on while an action records.
- ui.action.playAt {set, action} plays an action by its place, as the
  buttons do.
- An action without a color is an ordinary button. The bottom bar shows
  only Stop Playing/Recording while an action plays or records, and Play
  Current Selection while one waits at a stop. Menu items for a selected
  action or the current set are off in Button Mode.

Docs: docs/mcp.md, docs/ui-parity.md, docs/target-app-parity.md.
2026-11-13 17:26:31 -08:00
dotCooCoo edd2b83d1d i18n: Simplified Chinese has a row for 1,813 of the messages the untranslated report lists
Adds 1,813 @msg rows to zh-hans.tsv, one for each status and error message the
untranslated report listed for Simplified Chinese, except the 38 that open
pull requests translate in their own rows: the composite font, justification
order and Blob Brush connect end errors. The catalog test rejects a second row
for the same key, so leaving them out keeps the catalog consistent when those
pull requests merge.

The report now lists 40 zh-hans messages: those 38, and two that no catalog
has a row for yet. Its menu, tl!, undo label and swatch name sections are
unchanged. Placeholders, backticked names, quoted values and JavaScript
identifiers stay as in the source.

Docs: docs/localization-parity.md (zh-hans row), docs/target-app-parity.md.
2026-11-13 17:25:55 -08:00
dotCooCoo f3d04df7b8 i18n: Dutch has a row for the messages the untranslated report lists
The Dutch catalog lacked a row for 1,813 of the status and error
messages that the untranslated report finds in the sources, so the
status bar showed those messages in English.

- nl.tsv gains 1,813 `@msg` rows: the errors of commands and their
  parameter checks, scripts, file import and export, printing and
  plug-ins. The translations are VectorCraft's own, written from the
  English meaning with the catalog's conventions and its existing
  feature names. Placeholders, parameter names, command ids and
  literal values stay as the English writes them.
- The untranslated report lists 41 Dutch messages after the change:
  the composite font errors, the justification spacing error and the
  `connect` end error, which open #7211, #7116 and #7330 translate,
  and three unknown-parameter and range errors that open #7353
  rewrites so that a catalog row can match them. Menu strings, `tl!`
  literals and undo labels are unchanged.
- The row for `{k} has control characters{_1}` does not match the
  message for a multi-line File Info field, where the last
  placeholder is empty.
- docs/localization-parity.md's Dutch row and a line in
  docs/target-app-parity.md give the new counts.
2026-11-13 17:24:24 -08:00
dotCooCoo de8ac51502 Symbols: a stained instance keeps its stain in SVG, PDF and the other exports
A symbol instance colored with the Symbol Stainer lost its stain in
export whenever the canvas's stained art was not used:

- An instance with geometry effects was reshaped for export from the
  symbol's art with only its dynamic changes, so SVG, PDF, EPS, .ai,
  DXF, EMF/WMF and HPGL wrote the unstained colors. A color adjustment
  on an instance recolored the unstained art the same way.
- PDF, EPS, legacy .ai, DXF and EMF/WMF wrote an instance without
  effects from the unstained art.

tint_node, stain and instance_art now live in
vectorcraft_doc::symbol_overrides, which both the effects and the
exporters can use; vectorcraft_brush re-exports them. Baking, color
adjustments and the writers above now use instance_art: dynamic changes
first, then the stain.
2026-11-13 17:24:06 -08:00