winit 0.30 delivers no file drops on native Wayland. The new Linux Display
Server preference (Automatic / X11 (XWayland), shown on Linux only, read at
startup) has winit open the window on X11 when the session is Wayland,
DISPLAY is set and the X11 libraries winit loads are installed (ldconfig
check ported from PhotoCraft); otherwise the window opens on Wayland and
the log says why. README, development notes, parity docs, ROADMAP and the
complete catalogs updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A marquee drawn wholly inside a filled shape counted as touching it, so
a marquee over a background (the usual way to pick small objects off it
in Outline view) selected the background too. As in Illustrator, the
marquee now needs the path itself: an anchor inside it or a segment
crossing its edges.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Object › Path › Offset Path (and `ui.menuDialog` for it) opens on the
offset, joins and miter limit of the last time OK was pressed, as in
Illustrator, instead of 10 pt and Miter every time. The values are kept
with the rest of the remembered dialog options.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Effect › Distort & Transform › Zig Zag… lays out its options the way
Illustrator's dialog does: Size and Ridges per segment each have a
slider beside their field, Relative / Absolute are radio buttons under
Size, and Points offers Smooth and Corner as radio buttons instead of a
dropdown. The label reads "Ridges per segment".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A corner is now any anchor that isn't smooth where two sides meet at an
angle, straight or curved, as in Illustrator. The cut meets each side at
its setback measured along the curve, leaves both sides along their
tangents there, and each curved side is trimmed to what the cuts at its
ends leave of it. The largest radius is still the one taking the cut
halfway along the shorter side, measured along the curve. Corners
between straight sides draw exactly as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A property test of the importers (import_fuzz) crashed CI with
STATUS_STACK_BUFFER_OVERRUN: a shape with coordinates in the 1e20s from a
mutated file made vello_cpu either panic in flatten_simd on a rayon
worker (rayon then aborts the process, so the engine's panic guard never
sees it) or ask for a 132 GB allocation, which aborts too. A malformed
file could end the app and lose the user's work.
draw_shape now leaves a shape undrawn when its control points, through
the view, aren't finite or reach past 1e10 pixels, or a visible stroke
is that wide (MAX_DEVICE). A document's art stays within 4 million
points, 2.6e9 pixels at the closest zoom, and vello was checked safe
with 90,000 random shapes within 1e9 pixels and 30,000 within 1e12.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Artboard tool and the Artboards panel only ever had one artboard
selected, so Shift-clicking another didn't add it. As in Illustrator:
- Artboard tool: Shift-click adds an artboard to the selection (it
becomes active) or takes one out; a plain click on a selected one keeps
the selection, so a drag moves them all (Alt copies them all, the
copies becoming the selection), and Delete removes them all, one
artboard always staying. The other selected artboards show dashed
bounds; `selected` is a tool option.
- Artboards panel: with the Artboard tool, Shift- or Ctrl/Cmd-click on a
row adds or removes it, every selected row is highlighted, and Delete
Artboard removes them all.
- `artboard.move` and `artboard.delete` take `indices` besides `index`:
several artboards in one undo step, each with its art (an object moved
once where artboards overlap).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Icons are drawn in the theme's colour. The Selection tool's filled arrow
therefore came out light in the dark themes and the Direct Selection
tool's hollow one dark, so they looked swapped to anyone who knows the
black Selection and white Direct Selection arrows (reported by a user).
Both arrows now paint a fill in a fixed colour (black, white;
dc-arrow-fill.svg, original) under their outline in the theme's colour.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ••• button at the bottom of the toolbar no longer opens All Tools as a
centred dialog. It opens the All Tools drawer beside the toolbar, next to the
button. Escape or a click outside closes it; a click in the toolbar doesn't.
Tools that are already in the toolbar show dimmed in the drawer.
While the drawer is open the toolbar can be edited, as the public
documentation describes:
- drag a tool from the drawer onto a toolbar button's top or bottom edge
(left or right edge in two columns) to put it in its own slot there;
- drag it onto a button's middle to add it to that button's group;
- drag a toolbar button into the drawer to take its tool out;
- drag a toolbar button to another place in the toolbar to move its tool.
A line or outline shows where the tool will go, and the dragged tool follows
the pointer. While the drawer is closed the toolbar can't be edited.
The Basic and Advanced toolbars each keep their own edits in
UiState::toolbar_edits, which is saved with the preferences. It is serde
default, so older preferences still load, and a hand-edited file is cleaned
up when it loads. An edit that brings back the default toolbar clears the
saved edits. New UI commands toolbar.addTool {tool, slot?, place?},
toolbar.removeTool {tool, group?}, toolbar.reset and
window.editToolbar {open?} let MCP and the control channel make the same
edits. The drawer also has a Reset button.
The drawer moved from dialogs/all_tools.rs into the new edit_toolbar.rs. It
is tested with headless egui frame tests driven by pointer events (placement,
Escape, click outside, dimming, drag and drop in each direction, the locked
toolbar), along with command, persistence and drop-zone tests. The three new
command labels are translated in every complete catalog, and the error
messages reuse existing translated templates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A star's inner radius was always half its outer one while drawing, so
its ratio couldn't be changed. As Illustrator documents for the Star
tool: Ctrl/Cmd during the drag keeps the inner radius where it is while
the outer one follows the pointer (the new ratio stays once the key is
let go, for the rest of the drag and the next stars), and Alt keeps the
star's shoulders straight (each point's sides in line with the next
points', a ratio of cos(2π/n)/cos(π/n); five points or more).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Placing an SVG fitted and centred it by its art's bounds whatever `crop`
said, so art drawn on a shared canvas lost its place and scale, and
`crop: "crop"` and `crop: "bounding"` gave the same result without a
warning. With `crop: "crop"` given, an SVG is now framed and clipped by
its viewBox (its artboard, as File › Open has it), as a PDF is by its
page: `rect` and `at` fit and centre that frame. By default, as
Illustrator places an SVG, and with "bounding", it is still its art's
bounds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A browser's Copy Image puts the picture on the clipboard with text next
to it. Paste already took the picture when that text was only the
image's address (#597), but some browsers (seen on Fedora with KDE) put
the image's HTML there instead, `<img src="…" class="…" style="…">`,
which isn't an address, so the markup was pasted as type.
names_a_picture also takes markup whose only content is <img> elements
(no text outside its tags) as naming the picture, and Paste then reads
the bitmap. Markup with words in it, and an address alone, still paste
as text.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Fill/Stroke proxy stayed 36 pt and the Color, Gradient and None
buttons 7.5 pt in both toolbar layouts, so in two columns they sat small
in a wide strip and were hard to hit (in one column too). The proxy is
now 54 pt in two columns, the three buttons 11 pt in one column and
17 pt in two, and in two columns Draw Normal, Draw Behind and Draw
Inside sit side by side, each setting its mode (view.drawMode {mode}),
as Illustrator's two-column toolbar shows them; one column keeps the
button that cycles them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crash: rfd's blocking dialog ran -[NSSavePanel runModal] inside
winit's event handler; when a resize of the panel ends, AppKit runs the
closures winit queued meanwhile, and winit's re-entrancy panic fires
inside an Objective-C block, where it can't unwind, so the app aborts.
As PhotoCraft (#673) and PdfCraft (#145) ship it:
- macOS: picks::ask shows an rfd::AsyncFileDialog as a sheet on the
window (beginSheetModalForWindow returns at once); a waiter thread
sends the paths and wakes the window. A pick asked outside an entry is
refused and logged instead of running a modal. Linux keeps its thread
(#592) and now also wakes the window; Windows is unchanged.
- Nine paths that asked outside an entry now run as entries: Load
Profile, Swatches and Graphic Styles Other Library, the shortcut
editor's Import and Export, and the presets dialogs' Export.
- While a dialog is open: the macOS menu bar is inert except Hide, Hide
Others and Minimize; Quit, Close, Close All and the close button are
refused; Finder/Dock opens and the IME discard wait; another dialog
is refused with a status message. The answer re-activates the
document that asked (by uid) and Save Changes finds its document by
uid; a frame guard clears a stale picks entry after a recovered panic.
- ui.inspect reports fileDialog.
Squashed onto current main by the maintainer (with main's automation
sandbox wrappers and font-name menus kept).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The paragraph alignment shortcuts were missing. Cmd/Ctrl+Shift+L, C and
R align the selected type's paragraphs left, centred and right, J
justifies them with the last line aligned left and F justifies all
lines; while the Type tool edits text they act on the paragraphs its
selection touches, through the Paragraph panel's own path. They are UI
commands (type.alignLeft, …), listed in Keyboard Shortcuts, and enabled
while type is selected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The name was placed at the top-left corner of the artboard's bounding box
on screen, which a rotated view (Rotate View) turns away from the
artboard's own corner, so the name floated off beside it. It now sits
above the artboard's top-left corner as the view maps it, no wider than
the artboard's on-screen width.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`hdiutil makehybrid -hfs` gave every file in the image a
com.apple.FinderInfo, which `codesign --verify --strict` rejects as
"Finder information, or similar detritus" on the app in the DMG and on
copies installed from it, so compliance and MDM checks reported the
notarized app as damaged. As PdfCraft did (storytold/pdfcraft#823,
shipped in PdfCraft 0.6.0), the DMG is now made with
`hdiutil create -srcfolder -fs HFS+ -format UDZO`, retried when a CI
runner's device is busy, and the app mounted from the finished DMG must
pass `codesign --verify --strict --deep` before the release goes on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since #1025 reads global colours, more Illustrator EPS files open through
their layers, and for one reported file that gave a worse result than its
page did in 0.8.0:
- the page became the editing data's artboard (344 pt tall) instead of the
file's own bounding box (358 pt), cutting off art reaching above it. An
EPS whose page is its art's box now keeps that page on the layers path
too, as it does on the page path.
- prune_unseen took out text objects the page does draw: a red stroke
stacked over a dark red one differs from it by less than the lightness
margin, so the page looked no different without it. Pruning now weighs
each text object by colour (any of red, green, blue more than 64 apart);
the page check itself still compares by lightness, so colours written
as their CMYK equivalents still match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stroke.widthPoint.set and .copy read `index` with `as_u64() as usize`:
a malformed index ("bad", -1, 1.5) was taken as no index, so set added a
new point instead of failing, and a huge one wrapped round on wasm32.
They now read it through point_indices, as remove does since #1079:
anything but an index of an existing point is "no such width point".
A null index is still no index (set adds a point).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The theme leaves egui's own checkbox without an outline while inactive,
so an unchecked box was invisible and a checked one a bare tick. #1080
moved Preferences to widgets::check; the remaining ui.checkbox uses
follow: the Properties panel's Snap to Point, Snap to Grid and Scale
Strokes & Effects, Revolve's Keep visible surfaces and Shading, Save
options, Export for Screens, the Variables dialog and plug-in forms.
widgets::check_name shows a document's name (an artboard's, an asset's)
as it is, never translated; the check and radio rows translate their
labels in the public functions, so choice_row draws text as given.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
point_indices moves from freeform.rs to the cmd param helpers so
stroke.widthPoint.remove parses `index` and `indices` with it, and a
malformed entry reports the translated "no such width point".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new id errors reuse messages the catalogs already translate
(`ids` must be an array of object ids, object ids are non-negative
integers, no such layer or object), so complete_languages_translate_every_message
keeps passing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a .ai's layers can't be read from its editing data yet, it opens as
its PDF part, which lists the artboards as pages; those were laid out in
a row, so a grid of artboards (or any other arrangement) was lost. The
editing data's artboards are now read even then (ai::artboards, as far
as the reader gets) and, when there are as many as pages and of the same
sizes, each page goes where its artboard is, with the art on it (the art
of a page: the objects mostly on it, else nearest it). Otherwise the
pages stay in a row as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Align and Distribute Spacing move a selected compound path or group as
one object, and they found the key object only when its own id was
among the objects they move. When the key was inside a compound path
or a selected group, aligning to the key moved that compound path or
group like any other object, and the key moved with it. In that case,
Distribute Spacing with a spacing held the first object still instead
of the key.
The key object can end up inside a selected group or a compound path.
Dragging its row into a group in the Layers panel (layer.move) keeps
the selection and the key. A Selection-tool Shift-click on that group,
when it is unselected and directly in a layer, then adds it to the
selection (select.toggle) and keeps the key. Other ways of adding the
group keep the key as well: a Shift-click in the Layers panel's
selection column or on the group's target circle, a Group Selection
click that hits the key itself, select.add, and select.anchors or
select.anchorsMany in add or toggle mode. In isolation mode, a
Selection-tool click on one of several selected objects in the
isolated group makes that object the key. In an isolated compound
path, the same click on the outline of a selected member makes that
member the key.
Align to the key object and Distribute Spacing with a spacing now keep
in place the selected object that is the key or contains it. Both
commands look for that object among the key and its ancestors, so a
group around the key's group also stays in place. Aligning to the key
still lines the others up with the key's own bounds.
Docs: docs/target-app-parity.md.