Commit Graph
3849 Commits
Author SHA1 Message Date
BFlat ef666b4bfd Merge pull request #2738 from dotCooCoo/fix/file-names-windows-characters
Export: names typed into file names follow Windows' naming rules
2026-10-18 01:54:31 +07:00
BFlat e26393c7d8 Merge pull request #2740 from dotCooCoo/fix/clippy-1-95-artistic-filters
Effects: vectorcraft-effects passes clippy on Rust 1.95, the minimum toolchain
2026-10-18 01:54:16 +07:00
BFlat ba69d744ae Merge pull request #2745 from dotCooCoo/fix/issue-2558-drag-preview
Part of #2558: a drag draws zoomed-in raster effects at a lower resolution until it ends
2026-10-18 01:54:01 +07:00
BFlat 879fb63248 Merge pull request #2747 from dotCooCoo/fix/batch-extension-from-format
Actions: Batch's Override Save and Export name files with the format's extension
2026-10-18 01:53:47 +07:00
BFlat 5b7411e9d1 Merge pull request #2760 from dotCooCoo/fix/ai-import-difference-note-counts-art
.ai import: the warning that the layers differ from the page gives the art's share or names the type
2026-10-18 01:53:32 +07:00
BFlat b5715f7509 Merge pull request #2761 from dotCooCoo/feat/artboards-select-all
Artboards: Ctrl/Cmd+A in the Artboards panel selects every artboard with the Artboard tool
2026-10-18 01:53:16 +07:00
BFlat 66cfc1dca6 Merge pull request #2764 from dotCooCoo/feat/history-panel-step-backward-forward
History: the panel menu has Step Backward, Step Forward and Set History Limit…
2026-10-18 01:53:00 +07:00
BFlat 74cf04fa3b Merge pull request #2767 from dotCooCoo/fix/preset-rename-writes-before-removing
PDF presets: a rename that can't be written keeps the preset under its old name
2026-10-18 01:52:45 +07:00
BFlat fda352cf7b Merge pull request #2766 from dotCooCoo/feat/place-docx
Place: Word .docx files place as area type with their formatting
2026-10-18 01:52:31 +07:00
BFlat 98fc8146dc Merge pull request #2770 from dotCooCoo/feat/tiff-ccitt-g3
TIFF: CCITT Group 3 compressed files open and place
2026-10-18 01:52:16 +07:00
BFlat 3988aafc1a Merge pull request #2772 from dotCooCoo/fix/marquee-skips-shaper-sources
Shaper: a marquee does not select a Shaper Group by the original shape of an erased face
2026-10-18 01:52:01 +07:00
BFlat 2433c44915 Merge pull request #2773 from dotCooCoo/feat/optical-margin-alignment-follows-thread
Type: Optical Margin Alignment is a setting of the whole thread
2026-10-18 01:51:45 +07:00
BFlat dfde775213 Merge pull request #2757 from dotCooCoo/fix/saved-text-sizes-in-range
Type: sizes, scales, leading, indents and spacing out of range in a file are read in range
2026-10-18 01:51:28 +07:00
BFlat 2fa0e979f3 Merge pull request #2728 from dotCooCoo/fix/saved-script-sizes-in-range
Type: superscript, subscript and small caps proportions out of range in a file are read in range
2026-10-18 01:51:15 +07:00
BFlat eba745e354 Merge pull request #2471 from VL420/feat/task-bar-more
G1: Contextual Task Bar: Join, Edit Path, Release and type conversion by selection
2026-10-18 01:50:59 +07:00
BFlat 64fda576b2 Merge pull request #2787 from storytold/pr/2706-colored-lights
3D effects: one to ten coloured lights (#2706)
2026-10-18 01:50:40 +07:00
BFlat 07bf1ddf8c Merge pull request #2395 from EricKuck/fix/ai-outer-glow-solid-silhouette
Shadows and glows: each is of the art with the ones before it in the stack, and an Outer Glow blurs a solid silhouette
2026-10-18 01:50:04 +07:00
BFlat cc5fba7577 Merge pull request #2643 from makesomethingshit/fix/2544-blend-spine-anchor-tool
Blend: edit spine points and handles with the Anchor Point tool (#2544)
2026-10-18 01:49:51 +07:00
BFlat 95427b71bf Merge pull request #2720 from MarekSpodBiedry/issue-2655
Magic Wand: only select objects inside the isolated group (#2655)
2026-10-18 01:49:34 +07:00
BFlat c9bebb92d6 Merge pull request #2721 from MarekSpodBiedry/issue-2673
Map the WMF window onto the placeable box (#2673)
2026-10-18 01:49:20 +07:00
BFlat eaa21d42d5 Merge pull request #2722 from MarekSpodBiedry/issue-2693
Write legacy .ai layer names in Windows Latin-1 and warn when a character is replaced (#2693)
2026-10-18 01:49:06 +07:00
BFlat d5cfb27989 Merge pull request #2730 from nvict-service/i18n-nl-complete
i18n(nl): complete the Dutch catalog
2026-10-18 01:48:56 +07:00
BFlat a7fded4584 Merge pull request #2732 from vangel76/fix/2491-fallback-glyph-style
Fonts: fallback glyphs keep bold/italic, Bold Italic of a missing family keeps the bold, CJK prefers an installed sans (#2491)
2026-10-18 01:48:39 +07:00
BFlat 3e09a469de Merge pull request #2733 from vangel76/fix/2521-variable-default-face
Fonts: a variable font's default face is named and weighed by its default instance (#2521)
2026-10-18 01:48:25 +07:00
BFlat 079cd4983e Merge pull request #2739 from guillehr2/fix/1876-artboard-options-xy
Fix #1876: Artboard Options has X and Y with a reference point
2026-10-18 01:48:09 +07:00
BFlat 1651e7bea7 Merge pull request #2775 from VL420/feat/roman-hanging
G4: Paragraph panel menu › Roman Hanging Punctuation
2026-10-18 01:47:57 +07:00
dotCooCoo 6b13dd776b Export: names typed into file names follow Windows' naming rules
Export for Screens, Batch over data sets, Save for Web and the
Libraries panel name files after text the person typed: a prefix, a
suffix, a name pattern, the name of an artboard, asset, layer, slice,
data set or library, or the document's title. The prefix, the suffix,
name patterns and Batch's data set names had only /, \ and : replaced,
so on Windows a name holding <, >, ", |, ?, * or a control character
failed to save, and Save for Web without a path named its files after
the document's title as it was. A row folder name could end in a
period, which Windows does not allow, and names such as CON, NUL, COM1
or LPT1, which Windows reserves for devices, were written as they
were.

file_part, which Export for Screens' prefix and suffix and Batch's
data set names use, now writes all of those characters as -, and name
patterns use it in place of their own copy. A new safe_file_name runs
a whole file or folder name through file_part, removes trailing
periods and spaces, and adds - after a device name that is the whole
name or comes before its first period (CON.png becomes CON-.png).
Export for Screens uses it for each file, folder and zip it names, and
keeps item names distinct after it. Save for Web uses it for slice
images and, without a path, for files named after the title. Library
files use it too. This happens on every platform. Other names are
written as before, except where a changed name now equals another
item's name, which then gets a number added.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-18 01:27:13 +07:00
dotCooCoo 26af00d108 Effects: vectorcraft-effects passes clippy on Rust 1.95, the minimum toolchain
With Rust 1.95, the workspace's rust-version, cargo clippy --workspace
--all-targets -- -D warnings stopped at vectorcraft-effects: clippy 1.95
reports nonminimal_bool on the parameter and pixel-size guards of
Cutout, Poster Edges and Neon Glow, and on the size check in
Rasterize::compose (Effect › Rasterize). Clippy 1.99 does not report
them.

Each check now has the form clippy suggests, one !(a && b && ...) in
place of !a || !(b && c) (!a || !b || !(c && d) in compose). The
operands and their order are unchanged, so the filters and compose
return early in the same cases as before.
New tests check that the three filters leave the art unchanged for a
pixel size of 0, -1, NaN or infinity and for non-finite parameters,
and that compose leaves the raster unchanged when a buffer's length
does not match its size or the image's area has no positive width or
height.
2026-10-18 01:27:13 +07:00
bflatastic 6e29afe648 Render: the drag budget for shadows returns None, as the cached-shadow path does since #2395 (#2745) 2026-10-18 01:27:13 +07:00
dotCooCoo 7f858a7e59 Actions: Batch's Override Save and Export name files with the format's extension
With Override Save or Override Export on, action.batch named each
step's file in the destination folder with the step's format exactly as
written. The save and export commands read the format in any case and
with a leading dot, so a step with "format": ".svg" wrote
"Untitled_a..svg", "SVG" wrote ".SVG", "png8" wrote ".png8" and
"template" wrote ".template".

The file now ends in the format's extension: the extension as written,
in lower case and without the dot, when it is one of the format's
(".JPEG" gives ".jpeg"), and otherwise the format's first extension, the
one Export and Save use for a file name ("png8" gives ".png", "template"
gives ".vctemplate"). An unknown format ("xyz") keeps its spelling, and
the step fails with the command's error as before.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-18 01:24:35 +07:00
dotCooCoo dc48ce6c74 .ai import: the warning that the layers differ from the page gives the art's share or names the type
When a .ai or EPS opens from its editing data and its layers draw a
little differently from the file's own page, the warning gave the share
of all the pixels that differ, type included, and blamed brush strokes
and live effects. Type that the import lays out again from the file's
text, or draws in another font, raised it on its own: a line that the
page sets in pieces gave "about 1.5% of it (brush strokes, live effects
and the like ...)" with no art differing.

The comparison now also counts the pixels that differ away from type.
The warning gives that share, and when the art away from type does not
differ by more than the warning's limit, the warning names the type
instead. The warning appears in the same cases as before, and the
limits that make the file come in as its page are unchanged.

Docs: docs/target-app-parity.md.
2026-10-18 01:24:35 +07:00
dotCooCoo ceddd8185f Artboards: Ctrl/Cmd+A in the Artboards panel selects every artboard with the Artboard tool
With the Artboard tool in use, Ctrl/Cmd+A after a click on a row of the
Artboards panel selected all the art. The panel now takes the keyboard
when one of its rows is clicked, as the Layers panel does for Delete,
and gives it up when the pointer is pressed outside its list or the
panel is not drawn.
While it has the keyboard and the Artboard tool is in use, Select All's
keys, and Select All in the macOS menu bar, select every artboard: the
active artboard stays active and the art's selection does not change.
Otherwise Select All still selects the art.

Docs: docs/target-app-parity.md.
2026-10-18 01:24:35 +07:00
dotCooCoo aeb9314e2c Part of #2558: a drag draws zoomed-in raster effects at a lower resolution until it ends
When zoomed in, an object with a texture, a blur or a shadow was slow
to drag. Filtered content whose on-screen area passes the 8.4 million
pixel raster budget keeps no raster, and a shadow or glow larger than
4 million pixels keeps none either, so every frame of the drag ran the
effects again over up to 8.4 million pixels. A drag that scales or
rotates an object runs them again at any zoom.

The canvas now renders a tool's drag with RenderOptions::dragging. In
such a frame the renderer draws filtered content within 1,000,000
pixels, at a lower resolution where it would need more, unless it can
draw the content from an earlier frame's raster. On the multithreaded
pipeline it does the same for drop shadows, outer glows and inner
glows. No raster made that way is kept. They count as moved rasters,
so a raster made over them is made again after the drag, and the
desktop canvas renders the frame after the drag on the render worker.
That frame renders them as a still frame does. A dialog's preview,
exports and printing render as before.

zoomed_drag_perf times a drag's frames at 100% to 6400% with and
without dragging.

Docs: docs/target-app-parity.md.
2026-10-18 01:24:35 +07:00
dotCooCoo 85fce6852e History: the panel menu has Step Backward, Step Forward and Set History Limit…
The History panel menu held only a disabled History Options… item. The
reference app's History panel menu has Step Backward and Step Forward,
which undo and redo a change, and Set History Limit, which sets the
number of History States.

The panel menu now has Step Backward and Step Forward. They run
edit.undo and edit.redo, and each is disabled when there is no step to
undo or redo, as Edit › Undo and Edit › Redo are. Set History Limit…
opens Preferences at Performance, where History States is set.

Docs: docs/target-app-parity.md.
2026-10-18 01:24:34 +07:00
dotCooCoo 6a2bb03ebf PDF presets: a rename that can't be written keeps the preset under its old name
Renaming a saved PDF preset (pdf.preset.save with newName) removed
the old file from the PDF Presets folder before it wrote the new one.
When that write failed, for example on a full disk, the folder held no
file for the preset, and the preset was gone at the next start.

The store now writes the new file first and removes the old one only
when that write succeeded. A failed write leaves the preset in the
folder under its old name. A rename that changes only the case of the
name writes the old file and then renames it, and the old file gets
its content back when the rename fails. The command still succeeds
when the folder can't be written, and the failure is logged, as
before.
2026-10-18 01:24:34 +07:00
bflatastic a209996da2 Docs: file-format-parity counts Word .docx among the formats placed (#2766) 2026-10-18 01:24:34 +07:00
dotCooCoo 1c4ead3703 Place: Word .docx files place as area type with their formatting
File > Place could not place a Word document: a .docx file was "not a
format VectorCraft reads". The reference app's File > Place reads
Microsoft Word files as text.

File > Place now reads .docx files, written from ECMA-376 Part 1
(WordprocessingML, Transitional and Strict), and sets their text as
area type the way a text or RTF file is placed. The package is read
through its relationships. The formatting comes from the document
defaults, the paragraph style (else the default paragraph style), the
character style (else the default character style), the styles each
is based on, and direct formatting. Bold, italic, caps, small caps,
strikethrough and hidden text are toggle properties: a style that
turns one on reverses the state the styles before it give.

Each run keeps its font (theme fonts from the theme part), size, bold
and italic, underline, strikethrough, all caps, small caps,
superscript or subscript (in Document Setup's proportions), raised or
lowered text and color. Each paragraph keeps its alignment, start,
end, first-line and hanging indents, space before and after, and
direction; the start indent of a right-to-left paragraph is its right
indent. Table cells are separated by tabs and each table row is a
paragraph. Text in insertions, hyperlinks, content controls and
fields' results is read. Hidden and deleted text, field instructions,
pictures, text boxes, headers, footers, notes and list numbers are
left out.

A ZIP archive named .docx, or one that holds word/document.xml, is
read as a Word document. fileio/zip.rs gains a reader for stored and
deflated files that checks each file's CRC. A package with more than
10,000 files, a part that unpacks to more than 16 MiB or nests
elements more than 256 deep, and a document with more than 4 MiB of
text or 100,000 paragraphs or runs are refused with an error. The
Place dialog lists Word files, and file.place, file.place.info and
file.place.queue report the format `docx`. .doc files are still not
read.

The Word document tests in tests_textimport.rs fail without the
change, and text_import_fuzz.rs places random and damaged packages.

Docs: docs/file-format-parity.md, docs/mcp.md,
docs/target-app-parity.md.
2026-10-18 01:21:31 +07:00
dotCooCoo dd466d79e4 TIFF: CCITT Group 3 compressed files open and place
1-bit TIFFs compressed with CCITT Group 3 did not open, place or
relink: the image decoder reads Group 4 only and refuses Compression 2
(modified Huffman) and Compression 3 (ITU-T T.4).

They are now decoded with hayro-ccitt, the CCITT decoder that EPS
import uses. Compression 2 rows start at a byte and have no EOL codes.
Compression 3 rows follow an EOL code and are one-dimensional, or, with
T4Options bit 0, one- or two-dimensional as each row's tag bit says.
Fill bits, FillOrder 2, either PhotometricInterpretation, strips and
tiles are read.

A file whose pixels would take more than the decoding allowance as
RGBA is refused as too large to draw. A strip or tile whose data ends
before its last row is refused as damaged, and so is a tile larger
than the allowance. The strips and tiles together are read from at
most as many bytes as the file holds.

Part of #1466.

Docs: docs/file-format-parity.md, docs/target-app-parity.md.
2026-10-18 01:21:30 +07:00
dotCooCoo 8fbd515d6c Shaper: a marquee does not select a Shaper Group by the original shape of an erased face
A Shaper Group keeps its original shapes as a transparent first child.
Clicks skip them outside Construction mode, but a marquee did not: one
drawn over the outline of an original shape whose face the group had
erased selected the group, where nothing is shown. Group Selection's E
marquee selected an original shape that lay inside it, and Direct
Selection's marquee and clicks selected the anchor points of the
original shapes.

The marquee now skips a Shaper Group's original shapes with the same
check clicks use, which moves into shaper_hides, and Direct Selection's
walk over the art it can pick skips them too. In Construction mode, with
the original shapes isolated, the marquee still selects them and Direct
Selection still selects their anchor points.

Docs: docs/shaper.md, docs/target-app-parity.md.
2026-10-18 01:21:28 +07:00
dotCooCoo c44fb242aa Type: Optical Margin Alignment is a setting of the whole thread
Optical Margin Alignment was stored and set per text object, so the
frames of one thread could differ. Turning it on in the first frame of
a thread left the lines in the other frames flush with their margins.

Type › Optical Margin Alignment and type.opticalMarginAlignment now set
every frame of a selected frame's thread, in one undo step, and the
reply's ids list them all. After any edit to a thread, its frames take
the setting of the frame that the edit turned on or off, else the
first frame's. Threading frames gives the thread its first frame's
setting, and frames taken out of a thread keep it. A file whose frames
of one thread differ opens with the first frame's setting in all of
them. This holds for native files and for documents restored from the
editing copy that an EPS, SVG, PDF or .ai file carries.

Threading text from an out port into existing area type
(text.thread.add with to) now flows the story into that frame at once.
Before, the story reached it only at the next edit of one of the
thread's frames.

Docs: docs/mcp.md, docs/target-app-parity.md, docs/type-parity.md.
2026-10-18 01:21:27 +07:00
dotCooCoo e5945c6795 Type: sizes, scales, leading, indents and spacing out of range in a file are read in range
A .vectorcraft file's type opened with the character and paragraph
values it held. With a size of 0, the characters were not drawn. With
a size, leading, horizontal scale, left indent or space before of
1.797e308, point type's bounds were infinite or over 1e308 wide or
high, and moving or scaling it failed with "result would exceed the
canvas".

These values are now read into range when a file opens, in the type of
the layers, symbols, graph designs, patterns and the pattern definition
that Cancel puts back in pattern editing mode, and in character and
paragraph styles. A size, horizontal scale or vertical scale of 0 or
less becomes 12 pt or 100%, and a negative leading becomes Auto. A
size, leading or scale past 4,000,000 (MAX_COORD) becomes 4,000,000,
and a baseline shift, indent or space before or after past 4,000,000
either way becomes 4,000,000 or -4,000,000. A tab stop is kept to the
0 to 100,000 pt that text.tabs.set takes. A leading of 0, which legacy
.ai import stores, and the sizes, scales and indents within these
limits that SVG, PDF and .ai import keep outside the panels' ranges
open as saved.

Docs: docs/mcp.md (Paragraph attributes per paragraph).
2026-10-18 01:21:25 +07:00
dotCooCoo 81574b1648 Type: superscript, subscript and small caps proportions out of range in a file are read in range
document.setup accepts a superscript and subscript size of 1 to 500%
and a position of -500 to 500%, and a small caps size of 1 to 200%.
text.setFormat copies these proportions into the characters it
formats. A .vectorcraft file's characters, character styles and graph
label styles opened with the proportions they held. With a superscript
size of 0, the superscript characters were not drawn, and with a
superscript or small caps size of 1.797e308, moving the type failed
with "result would exceed the canvas".

These proportions are now read as the nearer end of each range when a
file opens: in the type of the layers, symbols, graph designs, patterns
and the pattern definition that Cancel puts back in pattern editing
mode, in graph label styles and in character styles. Proportions in
range and the other character attributes open as saved.

Docs: docs/mcp.md (Small Caps, Superscript and Subscript).
2026-10-18 01:21:24 +07:00
VictorandClaude Opus 5.5 f7382b2844 G1: Contextual Task Bar: Join, Edit Path, Release and type conversion by selection
The task bar offers more next steps for each kind of selection:
- an open path: Join (closes it) and Edit Path (the Direct Selection
  tool); a closed path: Edit Path;
- a compound path: Edit Path and Release Compound Path;
- a clipping group: Edit Clipping Path and Release Clipping Mask
  instead of Ungroup and Isolate;
- an image selected with vector art: Make Clipping Mask instead of Unite;
- point or area type: Convert To Area Type / Convert To Point Type
  beside Create Outlines.

Buttons may now carry command parameters. "Edit Path" is translated in
every catalog; the other labels reuse the menu's. cargo xtask ci passes
all 9 steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:11:39 +07:00
alpha-rock 039a467dcb M9: add multiple colored lights to 3D effects
Add opaque RGB light color and up to ten independently adjustable lights to
Revolve, Extrude & Bevel, Inflate and Rotate. Keep light selection, Add/Delete,
selected-light gizmos and preview transactions on the existing command path.

Preserve legacy white-light Inflate polygons, paint composition and seam joins,
including the 0.05 seam minimum. Use shared smooth normals for colored Inflate,
and batch solid-fill RGB channel paths behind one surface clip. Keep source
paths editable and SVG/PDF output vector artwork.

Rebase onto main f7de3d6a, retaining both sides of progress docs and all 22
catalogs. Shade freeform points once through the shared paint mapper. Document
release measurements and a reproducible CLI fixture, including the remaining
source-gradient cost and the one-light timing tradeoff.

Validation: full cargo xtask ci passed all 10 steps; 7,978 tests passed, zero
failed and 11 ignored. Four legacy white-light PNGs match unchanged main byte
for byte. Three paired release bench/perf repetitions completed without busy
warnings; all six standard perf runs passed every budget. Two-light solid
Inflate improved from 136.2 to 96.8 ms/frame at 1200x1200, default eight threads.
2026-10-18 01:11:39 +07:00
EricKuckandClaude Opus 5.5 1f304f6a23 Shadows and glows: each is of the art with the ones before it in the stack, and an Outer Glow blurs a solid silhouette
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:11:39 +07:00
makesomethingshit 45c2b0b363 fix(blend): complete contribution checks (#2544) 2026-10-18 01:11:39 +07:00
makesomethingshit 85afe7caaf test(blend): preserve Shift reshape after main rebase (#2544) 2026-10-18 01:11:39 +07:00
makesomethingshit 92e33b1579 fix(blend): preserve Anchor Point picking priority (#2544) 2026-10-18 01:11:39 +07:00
makesomethingshit fa9a52bd71 fix(blend): match cursor, Shift radius and hidden-handle cases (#2544) 2026-10-18 01:11:39 +07:00
makesomethingshit 5f70f96a66 style(tools): match rustfmt in rebased spine anchor test (#2544) 2026-10-18 01:11:39 +07:00