With the Selection tool, a single selected grid repeat shows a handle below the grid (rows), one right of it (columns), one past its bottom-right corner (both) and sliders between its first two columns and rows (horizontal and vertical spacing), as the public Set grid repeat options page describes. Each drag previews object.repeat.options and commits as one Repeat Options undo step; Escape cancels, and a drag that ends where it began leaves no step. Bounding-box handles keep priority where they overlap, and the controls hide with the edges or the bounding box. Before, a drag there scaled the source or started a marquee.
Part of #2691.
Every pointer move of a frame went to whatever tool was active, so with
a fast mouse (or a pen) a tool whose drag preview is costly (the
Selection tool moving a large selection, Free Distort, the Width tool)
redid it for each, up to 64 times a frame.
Tool::wants_samples (default false) says a tool builds a stroke from
the drag's samples: the Pencil, Paintbrush, Blob Brush, Eraser, Knife,
Smooth and Path Eraser answer true (the Paintbrush through its wrapper),
the Join tool doesn't. The canvas still reads the frame's moves every
frame, so the macOS feed's pressures stay paired, but replays them only
to such a tool; every other tool gets one drag a frame at the latest
position. A frame whose moves end where the last frame's did still
reaches the tool.
Tests: only_the_freehand_tools_get_every_move_of_a_frame (Pencil,
Paintbrush and Blob Brush get the 19 moves before the last, Selection,
Direct Selection and Width none),
a_mouse_stroke_keeps_a_frame_that_ends_where_it_started,
the_freehand_tools_want_every_sample, and
a_mouse_stroke_keeps_every_move_of_a_frame now checks every position in
order, not only the count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The canvas hands a dragging tool every position the pointer passed
within a frame for pens and fingers (touch events) and for a macOS pen
(the stylus feed's moves, #852), but a mouse got the frame's last
position only: one sample per frame. A fast mouse stroke kept a
position every 10 to 20 px, too few for any Fidelity to follow the
hand, and fewer still while the app is busy and frames come slower.
frame_moves now keeps a mouse's moves as well, without a pressure (the
tool takes the host's latest, a mouse's being full; a pen's on X11
among them), with the same bound of 64 moves for a stalled frame, as
touch and pen moves already reach every tool.
Tests: a_mouse_stroke_keeps_every_move_of_a_frame (20 moves in one
frame reach the Pencil; it got 2 points before this change), and
frame_moves_keeps_touch_feed_and_mouse_samples_with_their_pressure
replaces the test that a mouse's moves were left out.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Pencil stroke always previewed as the path it draws, with its full
appearance: with a fill set, the fill flipped between the shape and its
inside-out as the stroke crossed itself or curved back, and hid the line
being drawn.
Pencil Tool Options get a Live preview checkbox, above Live curve
fitting, on by default and kept with the tool's other options
(`livePreview`, settings.rs). With it off, the stroke previews nothing
while it is drawn: a thin line follows the pen (the drag overlay the
Knife and Blob Brush already show), and the release, or a switch of
tool mid-stroke, draws the path with its fill and stroke, as one undo
step, as before. Escape still cancels the stroke. With it on nothing
changes. The Paintbrush has no such option and keeps previewing.
Public reference: Draw and edit paths using the Pencil tool,
https://helpx.adobe.com/illustrator/using/tool-techniques/pencil-tool.html
(lists Live preview and Live curve fitting among the Pencil's options).
The checkbox label is translated in all 24 catalogs.
Tests: pencil_with_live_preview_off_shows_a_thin_line_until_the_release
(tools), pencil_with_live_preview_off_draws_the_filled_path_on_release
(engine), and the freehand dialog test shows the checkbox for the Pencil
only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The message scan read the first argument of every error variant, so
for EngineError::Disabled it read the command id and missed the reason
the status bar shows. It also read error calls inside comments, such as
a commented-out bad(cmd, "..."), as messages that need catalog rows.
The scan now reads Disabled's second argument and removes // and
/* ... */ comments (nested ones included) before it looks for calls. A
// or /* inside a string or character literal does not start a comment.
Review: reading `1,000` as 1 would give someone who writes decimals
with a point a value a thousand times too small, with no sign that
anything went wrong; refusing it, as before, is the safer answer.
A number that reads as thousands (one to three digits, a comma,
exactly three digits, then at most a unit: `1,000`, `12,500 mm`) now
keeps its comma, so the field refuses it. `0,125` is still a decimal
(a lone 0 never groups thousands), as are `1,25`, `1,0000` and
`1,500+2`.
Typing an offset of `0,1` in Offset Path, in a document in
millimeters, put the field back to the value it had (1 mm), so it
looked as if values under 1 mm were refused. The length parser only
takes a point as the decimal separator, and a field drops text it
can't read.
The shared numeric fields (unit_field, bounded_field and opt_field)
now read a comma as the decimal separator when the text has no point,
so `0,1 mm`, `1,5+0,25` and `12,5%` work in every dialog and panel
that uses them. Text with a point keeps its commas, so `1,000.5` is
still refused. The engine, MCP and control channel keep the strict
format.
Replace glob imports (`use super::*`, `use crate::*`, `use sig::*`) with
the names each file uses, in scriptcheck, pdf, render, text and ui-egui.
No code changes.
- packaging/linux/package.sh: one verify_sha256 helper replaces the four
repeated printf|sha256sum -c pipelines.
- packaging/macos/package.sh: stapler_retry copies its positional
arguments into locals before use.
- swatch_options: f64::from(v) instead of v as f64 (same value; the
argument is an f32, so the conversion stays).
Highlight Substituted Fonts is now a preference in Preferences › Type,
next to Highlight Alternate Glyphs, on by default and saved with the
other preferences (`prefs.set highlightSubstitutedFonts`). The canvas
reads it through `RenderOptions::highlight_substituted_fonts` for every
open document; a document's own setup no longer decides it. File ›
Document Setup no longer shows the checkbox and keeps Highlight
Substituted Glyphs.
A file saved with Document Setup's Highlight Substituted Fonts off now
shows the pink highlight when it opens, while the preference is on.
The file still opens with the stored value, and saving it again keeps
that value.
`document.setup` no longer reports `highlightSubstitutedFonts`. It
ignores the key and adds a `warnings` entry that names `prefs.set` to
its reply, so an older reply passed back still applies its other keys.
The raster cache of type under a raster effect now also redraws when
Highlight Alternate Glyphs changes.
Pointer Events report a press of a pen's eraser end as the eraser button
(button 5). The browser build ignored that press. It now presses like the
tip, and the web runner writes the pen's samples into a stylus feed with
the end they came from, so the canvas selects the Eraser tool before the
press and the press erases. The next press of the tip selects the tool
used before, as on Linux and macOS. A hovering pen keeps the end it last
pressed with, since Pointer Events report no end while a pen hovers. A
mouse or finger takes the pen out of the feed; a palm rejected while the
pen presses does not.
Docs: docs/hardware-parity.md, docs/gaps.md (G14),
docs/target-app-parity.md.
With Windows Ink, winit reports a pen as a touch and drops its pen
flags, so on Windows the eraser end of a pen draws with the current
tool. The message hook that reads the barrel button now also reads
each pen pointer message's POINTER_PEN_INFO and writes the pen's
pressure and end into the canvas's pen feed: PEN_FLAG_INVERTED or
PEN_FLAG_ERASER is the eraser end. The canvas then selects the Eraser
tool and the tip brings back the tool used before, as on Linux and
macOS. A pen leaving detection range or the window, another pointer,
or a mouse message that Windows did not make from a pen or a touch
clears the feed, so a mouse presses fully.
Draw freeform paths with the Pencil tool says a small star appears on
the Pencil when it is ready to draw a freeform path, and Reshape paths
with the Pencil tool says the star disappears over a selected path the
drag reshapes. The Pencil cursor had no star.
- New Cursor::PencilNew: the Pencil's crosshair with a small star where
the closing cursor has its ring. It becomes the crosshair with Use
Precise Cursors and as a system cursor.
- The Pencil shows it before a press when neither find_extend nor
find_redraw (the lookups the press uses, within Edit Selected Paths)
finds a selected path under the pointer. Over such a path and while a
stroke is drawn, the cursor has no star.
Docs: docs/target-app-parity.md.
Art Brush Options' Width had no pen tablet option, so an art brush
drew at one width whatever the pressure. The Width row now has a
Fixed or Pressure menu and a second width. With Pressure the art is
Width wide at the lightest pen pressure and the second width at the
heaviest, following the pressure the Paintbrush recorded along the
stroke, and half way between the two on a stroke drawn without
pressure. brush.options takes width_mode and width_max; a brush
without them is saved as before.
Pencil Tool Options has a Live curve fitting checkbox, on by default.
With it off, the path shown while a Pencil stroke is drawn joins the
stroke's points with straight segments, and the release fits the curve
at the Fidelity, as it does with the option on. Choosing another tool
while a stroke is drawn also keeps the stroke fitted. The option is
saved with the tool's other options.
path.freehand takes fit (true by default): with fit false, a new path,
a continued path and a redrawn section join the points with straight
segments.
Move opened without Distance and Angle, so its first frame replaced the
values a control client set with ones computed from Horizontal and
Vertical, and OK read Horizontal and Vertical without the Distance and
Angle set since the last frame. Move now opens holding the Distance and
Angle of its offset, and OK applies a Distance and Angle set since the
last frame.
With Preview off, selecting a plain image after an Image Trace object
kept the panel on that object without saving its waiting settings. A
trace of the image then made the image's trace the panel's object, and
selecting the first object again showed its stored settings and lost the
change. The panel now keeps the waiting settings for the object it
leaves whatever is selected next.
After imageTrace.setView, screenshot and render_preview still drew the
tracing result, because ui.render renders with the export options and only
the canvas turns on trace views. Only the app window showed the view.
ui.render now takes traceViews. With traceViews: true, Image Trace objects
draw in the view set with imageTrace.setView, as on the canvas, both
headless and in the running app. screenshot and render_preview take
traceViews and pass it on; without it they draw the tracing result, as
exports do. The trace-and-style prompt names the argument.
A supersampled render drew Outline view's lines, type outlines and dotted
guides as little as a quarter of an output pixel wide, so they came out
pale gray. The renderer now scales those widths and the guides' dashes by
the supersampling factor in the larger frame, so the lines stay one output
pixel wide.
Docs: docs/mcp.md (render_preview, screenshot), docs/control-protocol.md
(ui.render).
ui.dialog.set stored any field name it was given, so a misspelled field
(`discrad` for `discard`) was kept without effect and the dialog then
ran with its old value. It now answers such a field with an error that
lists the dialog's fields, and leaves the dialog unchanged.
A dialog accepts the fields it holds, `__` fields, `discard` with a
discard button, `preview` with a live preview, the fields it reads
before a control adds them (each spec's `inputs`, for example Copy and
the object options of the Transform dialogs, Move's `distance` and
`angle`, the reference point, `path` of the export options dialogs,
`searchFolder`, Brush Options' `tips`, the Justification and
Hyphenation values that open blank, the Corners `kind` and `radius` of
corners that differ, the Gradient Stop popover's `color`, `opacity`,
`location` and `spread`, and a new artboard's `color` and display
marks), and the fields it passes to the command it runs: every
parameter of the generic `command` dialog's command, and the
`textureImage` that Load Texture… sets in the Glass and Texturizer
effects. Edit Selection now opens holding `deleted<i>` for each of its
rows, so setting a row number it does not have returns an error, and
Transparency Flattener Presets opens holding the selected preset's name
and options instead of adding them on its first frame.