Commit Graph
1887 Commits
Author SHA1 Message Date
dotCooCoo 8ca25c955e Status bar: the artboard navigator lists the artboards by number and name
The status bar's artboard navigator showed only the active artboard's
number between its first, previous, next and last buttons, and it had
no list of the artboards.

The number is now a drop-down field that shows the active artboard's
number and name. Its list shows every artboard by number and name, as
the Artboards panel lists them. Choosing one runs view.goToArtboard,
the command the buttons run, which makes that artboard the active one
(and the Artboard tool's, while that tool is in use) and fits it in
the window. The list lays out only the rows in view and at most one
more, and opens with the active artboard's row in view. In a test
build with 1,000 artboards, the two frames that open the list take
0.12 ms and 0.04 ms, and a frame with the list open takes 0.03 ms. The
timed frames are headless and draw only the status bar.

Docs: docs/target-app-parity.md.
2026-10-16 04:04:50 +07:00
dotCooCoo 5a5f1a0995 Properties: Edit Artboards renames the active artboard and opens Artboard Options
With the Artboard tool, the Properties panel showed the active
artboard's name as a label, and no control in the panel opened
Artboard Options.

The name is now a text field. Typing a new name and pressing Enter or
clicking elsewhere renames the active artboard in one undo step
through artboard.setProps, as the Artboards panel's rename does;
pressing Escape or leaving the field empty keeps the old name. A click
on the Artboard Options icon beside the field runs tool.options with
tool "artboard", which opens Artboard Options for the active artboard,
as a double-click on the Artboard tool's button does.

Docs: docs/target-app-parity.md.
2026-10-16 04:04:50 +07:00
dotCooCoo 799155cdd0 View: Rotate View turns the view to a preset angle, and view.rotate sets any angle
In the View menu, Reset Rotate View was the only rotation item. The
status bar's angle menu set its twelve preset angles by writing the
view's rotation itself, and no command took an angle to turn the view
to.

View › Rotate View now lists the status bar's angles (0°, 15°, 30°,
45°, 60°, 90°, 180°, -15°, -30°, -45°, -60° and -90°) and checks the
one the view is turned to. The new UI command `view.rotate {angle}`
turns the view to any angle about the center of the canvas and
returns the angle it set, normalized to (-180, 180] as a Rotate View
drag normalizes it. The menu's items and the status bar's angle menu
run it from one list of angles; the status bar sets the same angles as
before. Without a document the command returns "no document" and the
items are disabled. Run from the command palette, which passes no
angle, Rotate View opens a dialog that asks for the angle, with the
view's current angle filled in.

The de, it, ja, ko, pl, pt-br, ru, uk, vi and zh-hant catalogs have a
new "Rotate View" row. The strings the catalogs cover leave out the
angle labels, as they leave out Type › Size's point sizes.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 04:04:49 +07:00
dotCooCoo 1f6ef9dcf3 Export for Screens: the dialog opens with the Artboard tool's selected artboards checked
Export for Screens opened on the artboard choice the document last
exported with (all artboards by default), whichever artboards were
selected with the Artboard tool or in the Artboards panel.

While the Artboard tool is in use, File › Export › Export for Screens…
now opens with the artboards the tool has selected checked, and Export
Artboard writes only those. They are the artboards the Artboards panel
highlights, and they are checked even after a Full Document export.
With another tool in use, the dialog still opens on the saved artboard
choice. The other fields show the saved settings in both cases, and the
params text of file.exportForScreens describes the rule.

Docs: docs/control-protocol.md, docs/target-app-parity.md.
2026-10-16 04:04:49 +07:00
dotCooCoo fc0e926cda Effects: Free Distort's corners are dragged in its dialog
Free Distort's dialog showed the four corners as read-only text, and
so did the Appearance panel's inline editor. Only effect.apply and
effect.setParams could set them.

The dialog now shows a box in the proportions of the first selected
object's bounds with a handle on each corner. Dragging a handle moves
that corner, and the preview follows. A handle focused by a click or
Tab moves 1% of the box with each arrow key, and 10% with Shift. Reset
puts the four corners back on the box. Each handle has a
screen-reader name. On the corners row of the Appearance panel's
inline editor, Edit… opens the dialog.

Docs: docs/effects-parity.md, docs/target-app-parity.md.
2026-10-16 04:04:49 +07:00
dotCooCoo 940f425a01 Color panel: Hide Options comes back after a restart, and ui.colorPanel sets the mode and options
Show Options and Hide Options were kept in egui's temporary memory, so
the Color panel showed its options again after every restart. No
command set them or the panel's mode.

- `UiState::color_hide_options` holds Hide Options and is saved with the
  preferences. Its reader reads `true` as hidden and any other value as
  shown, so a bad value leaves the other preferences as they are.
- `ui.colorPanel {mode?, options?}` picks a mode as the panel menu does
  (the active color converts to the mode's model as one undo step) and
  shows or hides the options. It answers `{mode, options, shown}`. A mode
  the menu does not list, `lab` included, answers an error. The panel
  menu's Show Options and Hide Options call the command's function.
- `ui.inspect` reports the setting as `ui.color_hide_options`.

Docs: docs/control-protocol.md, docs/target-app-parity.md.
2026-10-16 04:04:49 +07:00
dotCooCoo ea59b066d4 Effect menu: Glowing Edges moves to a Stylize submenu under Raster Effects
On main, Glowing Edges… is listed in the Effect menu's vector Stylize
submenu, after Drop Shadow, Inner Glow, Outer Glow and Feather. The
reference app lists it in the Stylize submenu of its Photoshop effects,
below the vector effects.

The Effect menu now has a Stylize submenu under Raster Effects, between
Sharpen and Texture, and Glowing Edges is listed there. The menu sends
the effects at the Stylize path that PIXEL_EFFECTS names to that
submenu, and the vector Stylize submenu keeps its six effects. The
effect's id, its catalog entry, its effect.list entry and Apply Last
Effect do not change.
2026-10-16 04:04:49 +07:00
dotCooCoo 427cd65f30 Templates: Save as Template can also write a PDF-compatible .ait
File › Save as Template always wrote a .vctemplate. The save panel
offered only that type, file.saveAsTemplate ignored its format param,
and a name typed with .ait got .vctemplate added. New from Template
already opened a .ait as an untitled document.

Save as Template now also writes a .ait: the PDF-compatible file Save
As writes for .ai, carrying the document. The desktop save panel lists
VectorCraft Template first and the .ait type beside it, and the web
build's Save as Template dialog gets a Format menu with the same two
types. file.saveAsTemplate writes .ait for format: "ait", or for a path
ending in .ait when no format is given, and takes the .ai options;
file.formatOptions answers for ait. .vctemplate stays the default.
Exports and Export As still do not write .ait.

Docs: docs/mcp.md, docs/file-format-parity.md (.ait row),
docs/target-app-parity.md.
2026-10-16 04:04:49 +07:00
dotCooCoo c246fc2f0e Clipboard: a .svgz file copied in a file manager pastes as its art
Paste takes a file copied in a file manager by its flavor, which
file_flavour tells from the file's first 4,096 bytes through
fileio::detect. detect names gzip data SVGZ unless it is a compressed
native file, and file_flavour gave no flavor for the format id svgz.
So a copied .svgz file did not paste as its art, although
clipboard.importSvg, the SVG flavor's command, reads SVGZ data.

A copied file whose gzip data unpacks to SVG markup now pastes through
the SVG flavor. file_flavour unpacks the head it is given with the
gzip decoder the SVGZ reader uses, up to where the head ends, and
checks the first 4,096 unpacked bytes with looks_like_svg, as detect
checks an uncompressed file, reading them as UTF-16 after a UTF-16
byte order mark. Other gzip files get no flavor, as before.

Docs: docs/target-app-parity.md.
2026-10-16 03:36:20 +07:00
dotCooCoo c5a1504e99 Clipboard: a .ai or .ait file copied in a file manager pastes as its art
Paste takes a file copied in a file manager by its flavor, which
file_flavour tells from the file's first 4,096 bytes through
fileio::detect. detect names PDF or PostScript bytes in a file called
.ai or .ait by that extension, and file_flavour gave no flavor for
the format ids ai and ait. So a copied .ai or .ait file did not paste
as its art, while the same bytes in a .pdf or .eps file did.

A copied .ai or .ait file whose bytes are a PDF now pastes through the
PDF flavor (clipboard.importPdf), and one whose bytes are PostScript
pastes through the EPS flavor (clipboard.importEps). Other files
with those extensions paste as before. A .ai saved without its PDF
part also gets the PDF flavor, and Paste answers it with
clipboard.importPdf's error, as it does for the same file named .pdf.

Docs: docs/control-protocol.md, docs/development.md,
docs/target-app-parity.md.
2026-10-16 03:36:20 +07:00
bflatastic b9341d3b3b i18n(bg): the PostScript file error names File › Open and File › Place 2026-10-16 03:36:20 +07:00
dotCooCoo 31ffbb2152 PDF/.ai import: the PostScript file error names File › Open and File › Place, which read the file
document.pdfInfo and clipboard.importPdf, given a PostScript file (an
EPS, or an .ai in an older PostScript format), failed with "this is a
PostScript file (...), which can't be opened yet: save it as PDF,
PDF-compatible .ai or SVG". document.open and file.place read the same
file through the EPS reader. The error told users to convert a file that
VectorCraft opens.

The error now says the file is not a PDF and that File › Open and
File › Place read it as EPS. The 13 catalogs that carry the message get
the new text.
2026-10-16 03:36:20 +07:00
EricKuckandClaude Opus 5.5 f3b4c3ec78 PDF import: an axial or radial shading keeps its function's curve when sampled into stops
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:20 +07:00
bflatastic 136810bee2 PDF/.ai import: the tint transform test passes no ink names to space_of 2026-10-16 03:36:20 +07:00
dotCooCoo ca145c5265 PDF/.ai import: spot inks with the same values and different names keep their own swatches
A PDF can define spot inks that have different names and the same
alternate space and tint transform, such as Blue1 and Blue2, both RGB
0 0 255. The interpreter drops the ink name, so the importer matches an
interpreted color to the file's Separation and DeviceN spaces by the
tint transform. The spaces of two such inks matched the same color, so
their paths imported as plain RGB and neither ink became a spot swatch.
This happened with both inks on one page, with each on its own page,
and in the PDF part of a .ai file.

The page walk in import_scan.rs, which follows the interpreter's order
for layers and overprint, now also records the ink of each path, from
the color space set by cs and CS or from the shading of the pattern set
by scn and SCN or drawn by sh, and the ink of the color space of the
text between two paths. When the spaces of several inks match a color,
the importer takes the space with the walk's ink names. It applies
these names to a page only when the page uses such an ink and a
counting pass of the interpreter draws as many paths there as the walk
counted. Otherwise the import works as before.

The file now opens with a spot swatch for each ink. Solid fills and
strokes of paths and type, and the stops of gradients on paths, link
to the swatch of their ink, the points of a gradient mesh keep the
ink's color, and PDF export writes each ink as its own separation.
Paint in these inks inside pattern cells, soft masks and type 3 glyphs,
and gradients on type in these inks, still import as RGB. Type in one
of these inks can also import as RGB when type in another Separation or
DeviceN ink is shown with no path drawn between them.
2026-10-16 03:36:20 +07:00
bflatastic 90e6ff3de1 PDF/.ai import: the tests added on main pass the page's unit to layered_ai 2026-10-16 03:36:20 +07:00
dotCooCoo 16b8aeb6b7 PDF/.ai import: a .ai whose page has a UserUnit opens with its layers at the page's size
A PDF page's UserUnit (PDF 1.6) sets the size of its user space unit
in multiples of 1/72 inch. The PDF reader has applied it since #1894, so
a page with /UserUnit 10 and a 36 × 50.4 media box opens at 360 × 504
pt. A .ai whose editing data has its artboards in the page's own units
then no longer matched its PDF part. It opened from the PDF part,
without its layers, its hidden objects and the art outside its
artboards, and with its artboards in a row instead of where the
editing data puts them. document.pdfInfo gave such a page's size in
points and its boxes in the file's numbers.

Editing data whose first artboard has the page's size in the page's
units, and not in points, is now compared with the PDF part scaled
down by the UserUnit. The document read from it is then scaled up by
the UserUnit, with its stroke weights, dashes, effects and pattern
tiles. When the layers can't be read, the artboard layout taken from
the editing data is scaled the same way. document.pdfInfo gives the
boxes in points, as it gives the size.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 03:36:20 +07:00
dotCooCoo dc179c3671 .ai import: CMYK images in the editing data keep their ink amounts
When a .ai file, or an EPS with editing data, opened from its editing
data, the reader converted each embedded 8-bit CMYK image to RGB and
stored it as a PNG, so the document lost the image's ink amounts. When
the same .ai opens from its PDF part, the PDF importer keeps them in a
CMYK TIFF.

The reader now stores those samples with ImageBlob::cmyk_tiff, as the
PDF importer does (crates/pdf/src/import_image.rs). An alpha channel
that hides part of the image becomes the image's opacity mask, a
grayscale image over it, as in PDF import. Grayscale, RGB and 1-bit
images still open as RGBA PNGs.

Docs: docs/file-format-parity.md, docs/target-app-parity.md.
2026-10-16 03:36:20 +07:00
bflatastic 8af0459232 AI import: a gradient mesh keeps at most 65,536 points, however its patches are cut 2026-10-16 03:36:20 +07:00
EricKuckandClaude Opus 5.5 76888366e7 AI import: a mesh patch's anchors run in the mesh's direction whatever their key
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:20 +07:00
EricKuckandClaude Opus 5.5 1682d59b65 AI import: a gradient mesh patch's edges bend through the anchors listed between its corners
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:20 +07:00
EricKuck e93ba4c83f AI import: a gradient in a pattern's definition is placed from the canvas, as the file's PDF part draws it 2026-10-16 03:36:20 +07:00
EricKuckandClaude Opus 5.5 9ebd30b8bb AI import: a styled object read in place of its drawn look keeps the transparency written on the look
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:20 +07:00
EricKuckandClaude Opus 5.5 6545d8b886 AI import: a drawn look that is an image stands for its object, as one of paths does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:19 +07:00
EricKuckandClaude Opus 5.5 fb6fc437c3 AI import: a clipping path alone in a group clips the clipping group around it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:19 +07:00
midasmatterhorn d5a672fda2 eps: an opacity mask in the editing data is named, not drawn whole (#2004) 2026-10-16 03:36:19 +07:00
bflatastic 312a939646 eps: rustfmt the layer transparency change 2026-10-16 03:36:19 +07:00
midasmatterhorn 6feec01d85 eps: a layer's own transparency in the editing data is read (#2003) 2026-10-16 03:36:19 +07:00
NetterSilverandClaude Haiku 5.5 dfdb98463f Open PDFs and .ai files with an image over 256 MB decoded
Fixes #2005

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:36:19 +07:00
bflatastic 73f3731dbf Properties: the flip buttons keep the reference app's Properties names (#1910)
#2227 renamed them Flip Horizontal and Flip Vertical; what they do is unchanged. The reference app's Properties panel calls them Flip Along Horizontal Axis and Flip Along Vertical Axis (the Transform panel's menu keeps Flip Horizontal and Flip Vertical), so the labels and their catalog rows come back.
2026-10-16 02:56:55 +07:00
bflatastic 5e374712dc i18n(bg): Reset Tracking and Kerning 2026-10-16 02:56:55 +07:00
dotCooCoo cb9522f7cd Type: Cmd/Ctrl+Alt+Q resets tracking to 0 and kerning to Auto
The reference app resets tracking and kerning to 0 with Cmd/Ctrl+Alt+Q.
VectorCraft had no command for it.

type.resetTracking (Reset Tracking and Kerning, default Cmd+Alt+Q) sets
tracking to 0 and kerning to Auto, which the Character panel shows as 0,
in the text the Type tool has selected, or else in all the text of
every selected type object. At a caret it resets only the kerning of
the character before it, where Alt+Left/Right kerns. It is one undo
step. The range logic of type.step moves into a shared type_ranges.

When a call gives ids, type.step and type.resetTracking change all the
text of those type objects even while the Type tool edits text, as
paint.setFill does. Before, type.step changed the Type tool's selected
text instead.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 02:56:35 +07:00
dotCooCoo d726f6596c Layers: Ctrl/Cmd+Alt-click on an eye switches the other layers between Outline and Preview
A Ctrl/Cmd+Alt-click on a row's eye in the Layers panel ran Hide Others
or Show All Layers, as an Alt-click does. It now runs Outline Others for
the row's layer (layer.outlineOthers), or Preview All Layers
(layer.previewAll) when every other top-level layer is in Outline
already. Each is one undo step. Alt-click and Ctrl/Cmd-click on an eye
keep their actions.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 02:56:35 +07:00
sanyamsingh001andCodex 98511401a0 G1: Fix intermediate overflow in adjoining width adjustments
Co-authored-by: Codex <noreply@openai.com>
2026-10-16 02:56:35 +07:00
Marco Arnulfo f2f1945973 Paste in Place: art copied from off the artboards goes back where it was (fixes #1924) 2026-10-16 02:56:35 +07:00
dotCooCoo d35ed26b0f Fix #1692: tabbing through a hex field no longer resets the color
In the Color Picker, Tab out of an edited field gives the next field the
focus in the same frame, and the picker applies the edit once it has
drawn its fields. The # field after Y took the focus showing the color
from before the edit and kept that text while it had the focus, so the
next Tab committed it and reset every other field. Shift+Tab into the #
field from K had the same effect. Swatch Options and New Swatch draw a
copy of the field, and Tab from the last component field into it had the
same effect there.

widgets::hex_field and the Swatch Options copy now show the current
color until something is typed into them, also while they have the
focus, and commit only what was typed. The change covers the # fields of
the Color Picker, Swatch Options, New Swatch, the Color panel, Color
Themes, Recolor Artwork, Document Setup and Define Perspective Grid.

widgets::opt_field, which draws the Stroke panel's dash and gap fields,
kept its text the same way: passing through a blank gap after typing a
dash committed the blank, and the panel applied the same dash pattern
again. It gets the same change. When its value changes while it has the
focus and nothing has been typed into it, all of the new value is
selected, as on keyboard focus.
2026-10-16 02:56:35 +07:00
dotCooCoo aaa7359c7b Part of #1692: Tab in the Color Picker goes through one color model's fields before the next
The Color Picker drew its value fields as one grid, row by row. Tab
moves through the fields in the order they are drawn, so it went H, L,
S, a, B, b, R, C, G, M, B, Y, # and K, from one color model to the
other on every row.

HSB, RGB and the hex field are now in one grid, and Lab and CMYK are in
a second grid beside it. Tab goes through H, S, B, R, G, B and #, then
L, a, b, C, M, Y and K. The dialog looks as before: K's row is as tall
as the hex field's row beside it.
2026-10-16 02:56:35 +07:00
Marco Arnulfo 7608639021 Type: a colour picked while typing keeps what was typed (fixes #1950)
The Color panel and the Color Picker preview a colour in an interaction.
While typing, that interaction joined the open typing session and
previewed from the document before the typing, so new type came back as
its placeholder text. Typing in progress is now kept as its own step
before another interaction begins, as Undo already does.
2026-10-16 02:56:35 +07:00
Gert Pellin e6170de1a2 Transform commands: a string for an optional number is an error (#1952)
object.setBounds read x, y, width and height with f64_or, which falls back
to the current value for anything that isn't a JSON number, so
{"width": "60 mm"} returned ok and changed nothing. object.move,
object.nudge, object.rotate, object.scale (sy) and object.shear did the
same with their optional numbers. A value that is neither a number nor
null is now a BadParams error naming the key, as a missing required
number already is.
2026-10-16 02:56:35 +07:00
MarekSpodBiedry a0f8a88e82 Paint: picking another pattern swatch keeps the pattern transform (#1970) 2026-10-16 02:56:35 +07:00
Ayberk A. 6d898558fd i18n: the notes for an EPS or .ai whose layers weren't read are translated (#2035)
The importer wraps its reason in "the file's layers weren't read ({why}):
it comes in as its page, in one layer" (and, for an .ai, "... from its
editing data ({why}): they come from its PDF part"). The reasons had @msg
rows, the wrappers none, so after "Opened with 1 note(s):" the whole note
stayed English. The two templates are now in every language that
translates messages (and pt-br, which has the reasons), and the reason
inside is translated through them. These notes are pushed as warnings, so
the message scan doesn't see them: a test checks them in each language.

"<Clip Group>" already has a French entry on main; layer names such as
"Layer 1" are stored names and stay as they are.
2026-10-16 02:56:35 +07:00
Ayberk A. 5ff34782cb color.loadProfile: say that a loaded profile lasts for the run (#1955)
The profile is registered in the process's colour registry only, so the
next `vectorcraft-cli run` (or the next launch of the app) doesn't know it
and edit.colorSettings falls back to the built-in profile. The command's
description now says so, and that the profile has to be loaded again in
each run that names it. Keeping profiles across runs would need a place in
the preferences to remember them, which is left for the maintainers.
2026-10-16 02:56:35 +07:00
Ayberk A. 07c6b938bc Shortcuts: + selects the Add Anchor Point tool (#2142)
The tool's default key is "+", and `shortcuts::parse` split a bare "+" as a
separator with nothing on either side: the key part came out empty, so the
shortcut didn't parse, `tool_for_key` found no tool for a typed "+" and the
key did nothing. "-" (Delete Anchor Point) has no separator to trip on, which
is why it worked. A bare "+" is now the key itself, the "=" key, as "Cmd++"
already was, so "+" typed with Shift on a US layout, by a layout's own "+"
key or on the numpad selects the tool.
2026-10-16 02:56:35 +07:00
dotCooCoo 0155eaf468 3D and Materials: Inflate builds its edge index once
inflate built an edge index (Edges) of the shape's rings, and
Membrane::solve, which inflate calls first, built a second index of the
same rings. Membrane::solve now takes the index that inflate builds.

In a release build, one Edges::new takes 0.08 ms of the 27 ms that
inflate takes on a ring of 2,000 points, and 2.0 ms of 219 ms on a ring
of 1,000 spikes whose 2,000 edges fill 693,816 bucket entries. The
facets do not change: for nine shapes, three views and 96 combinations
of the Inflate settings, the Debug text of all 2,592 results is byte
for byte the same on main and with the change.
2026-10-16 02:56:34 +07:00
dotCooCoo 5a83bcfafa Export: the export commands' params and the MCP export tool list the .ai format
document.export, document.serialize and document.exportSelection write
a PDF-compatible .ai (format: "ai"), and document.formats lists ai as
writable, but none of their params texts named it. The params text of
document.exportSelection named only png, jpg, webp, svg, svgz and pdf,
although the command writes all 20 writable formats. The description
of the MCP export tool and its row in docs/mcp.md named every format
of the tool's format enum except ai, and the range text and the row
said that only PDF writes several artboards.

The three params texts now list every format their command writes,
and document.export's range and useArtboards texts name .ai beside
PDF. The MCP export tool's description names ai, and its artboard and
range texts say that .ai, like PDF, writes one page per artboard. The
range text and the row also say that SVG, SVGZ and EPS write one file
per chosen artboard, and that rasters, DXF, EMF and WMF do so with
options.useArtboards: true.

Docs: docs/mcp.md (the export tool).
2026-10-16 02:56:34 +07:00
dotCooCoo 66dbe40ea6 Export for Screens: the params text and the format error list every format a row writes
The document.exportForScreens params text listed png, png8, jpg, webp,
gif, svg, svgz and pdf for a row's format, and its settings keys left
out svgz. A row of another format VectorCraft writes, such as eps, was
refused with "Export for Screens writes png, png8, jpg, webp, gif, svg,
svgz or pdf". Rows of tiff, bmp, tga and psd are written too, and the
Export for Screens dialog offers TIFF rows.

The params text, its settings keys and the error now list the 12
formats a row writes: png, png8, jpg, webp, gif, tiff, bmp, tga, psd,
svg, svgz and pdf. Which formats a row accepts does not change.
2026-10-16 02:56:34 +07:00
Marco Arnulfo 53c59f06de PDF: an untitled document saved to a file exports titled after it (fixes #2166) 2026-10-16 02:56:34 +07:00
dotCooCoo 4a1323ad07 i18n: Russian Isolate and Sublayer rows use Cyrillic letters only
The Russian catalog's Isolate row began with a Latin "A" (U+0041),
"Aизолировать", and the Create New Sublayer and New Sublayer… rows
spelled "подслой" with a Latin "c" (U+0063). The rows now read
"Изолировать", "Создать новый подслой" and "Новый подслой…".

A new test fails when a word in any catalog's translation holds letters
from more than one of the Latin, Cyrillic and Greek scripts.
2026-10-16 02:56:34 +07:00
Justin Willhite 8da47f11f8 PDF export: a CMYK page without blending through is an isolated group (#2156) 2026-10-16 02:56:34 +07:00
bflatastic 18f8a1bdcf PDF import: a damaged array is refused as damaged, not as functions built on one another 2026-10-16 02:56:34 +07:00