Commit Graph
1714 Commits
Author SHA1 Message Date
bflatasticandClaude Opus 5.5 178f99d60e #983: supersample Art Optimized edges in exports
Asset Export, File › Export, Save for Web and Object › Rasterize drew
each shape with its own smoothed edge, so where two shapes met edge to
edge (Divide, Shape Builder, abutting art) both half-covered the pixels
on the line and the background showed through as a thin ghost border.

With Art Optimized (the default) these now supersample, as the option's
name in Illustrator says: the art is drawn with hard edges at four times
the size (three or two times for large images, within a 40-megapixel
budget and the renderer's 65,535-pixel side) and each block averaged
into one pixel. Pixels shared by two shapes are fully owned by one or
the other at the finer size, so no seam is left, and the outer edges
are still smooth. The canvas keeps shape-by-shape smoothing for speed;
None and Type Optimized are unchanged.

RenderOptions::supersample turns it on (exports and Rasterize set it).
A render test checks two triangles sharing a diagonal: a seam with
shape-by-shape smoothing, none supersampled, and the factor's limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 03:48:03 +07:00
BFlat c403e57d2a Merge pull request #1013 from Ni-zav/fix/991-shift-stepper-s20261010T1758Z-a74b
fix(widgets): apply Shift and Ctrl modifiers to numeric stepper buttons
2026-10-11 03:45:43 +07:00
BFlat e606c56064 Merge pull request #1012 from Ni-zav/fix/1000-object-mosaic-input-s20261010T1758Z-a74b
fix(dialogs): preserve integer counts in command parameter fields
2026-10-11 03:45:27 +07:00
BFlat d15bc61818 Merge pull request #988 from Ni-zav/fix/noissue-crop-box-option-s20261010T1630Z-c8d2e1
fix(crop): reject malformed crop rectangles without shifting coordinates
2026-10-11 03:45:10 +07:00
BFlat 428894df22 Merge pull request #999 from Ni-zav/fix/noissue-distort-geometry-validation-s20261010T1654Z-8d74ec
fix(distort): reject malformed warp geometry and explicit targets
2026-10-11 03:44:54 +07:00
BFlat 0cb1beaf21 Merge pull request #998 from Ni-zav/fix/noissue-path-anchor-validation-s20261010T1654Z-8d74ec
Fix/noissue path anchor validation s20261010 t1654 z 8d74ec
2026-10-11 03:44:37 +07:00
BFlat c05ad3985c Merge pull request #997 from Ni-zav/fix/noissue-anchor-selection-input-s20261010T1654Z-8d74ec
fix(selection): reject malformed anchor references without changing selection
2026-10-11 03:44:20 +07:00
BFlat 05bb1ac97f Merge pull request #996 from Ni-zav/fix/noissue-assets-explicit-targets-s20261010T1654Z-8d74ec
fix(assets): reject invalid object IDs before collecting export assets
2026-10-11 03:44:04 +07:00
BFlat 7915bfc0e1 Merge pull request #987 from Ni-zav/fix/noissue-stroke-input-atomic-s20261010T1630Z-c8d2e1
fix(stroke): reject invalid dash entries and keep defaults atomic
2026-10-11 03:43:47 +07:00
BFlat 219b9da346 Merge pull request #986 from Ni-zav/fix/noissue-rect-cut-input-s20261010T1630Z-c8d2e1
fix(cut): reject malformed rectangle cut bounds
2026-10-11 03:43:30 +07:00
BFlat 683f6439ca Merge pull request #985 from Ni-zav/fix/noissue-place-coordinates-s20261010T1630Z-c8d2e1
fix(place): reject malformed rectangle and position parameters
2026-10-11 03:43:14 +07:00
BFlat 67a0ffca4d Merge pull request #984 from Ni-zav/fix/noissue-paint-proxy-atomic-s20261010T1630Z-c8d2e1
fix(paint): preserve fill and stroke defaults when edits fail
2026-10-11 03:42:57 +07:00
bflatasticandClaude Opus 5.5 e0d494b2eb ROADMAP: the validation batch, Object Mosaic counts and stepper modifiers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:24:31 +07:00
bflatasticandClaude Opus 5.5 9e09d53fd9 Review #1013: the stepper test from #1015 compiles and hits the spinner
The headless test taken from #1015 set `RawInput::modifiers`, which egui
0.36 doesn't have, and clicked left of the spinner (the right-aligned
label's text ends before its box). Modifiers now come as
`ModifiersChanged` events, as the Appearance panel tests send them, and
the click is placed from the field's text. It also checks Ctrl/Cmd steps
a tenth. It fails with the spinner ignoring modifiers (15 pt for 24).
rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:14:00 +07:00
Nigel Ihza Firdausy 6d5fdc8a2a test(ui): Shift-click on the Stroke weight stepper steps 10 pt (#991)
The headless panel test of #1015, kept on top of #1013's fix (#1015's
own change to the spinner is superseded by it).
2026-10-11 02:06:41 +07:00
Nigel Ihza Firdausy 057c2ee2c1 fix(widgets): honor Shift on numeric spinner buttons (#991) 2026-10-11 02:06:20 +07:00
bflatasticandClaude Opus 5.5 5a9c6e2e06 Review #1012: whole numbers typed in command dialogs are integers
The PR kept a field's integer kind only while its value had been an
integer: typing 2.5 in Columns and then 3 sent 3.0, and the mosaic fell
back to 10 × 10 again. A whole number typed in any command dialog is now
an integer (`typed_number`) whatever the field held before; commands
that take any number read integers as well, and a fraction stays one.

Test: Object › Create Object Mosaic… opened from its menu item, 3 typed
over Columns and Enter makes a 3 × 10 mosaic (it made 10 × 10 before,
#1000).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:06:19 +07:00
Nigel Ihza Firdausy 130bacde12 fix(dialogs): preserve integral command parameters in numeric fields (#1000) 2026-10-11 01:59:54 +07:00
bflatasticandClaude Opus 5.5 311d75fc97 Review #988: rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:58:43 +07:00
Nigel Ihza Firdausy c845c7f9e0 fix(crop): reject malformed crop rectangles without shifting coordinates 2026-10-11 01:58:31 +07:00
bflatasticandClaude Opus 5.5 2ff5688511 Review #999: corners and from through finite_numbers; rustfmt
Same checks in a third of the code; the corners destructure into the
four points instead of being indexed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:51:12 +07:00
Nigel Ihza Firdausy 0d697ed79d fix(distort): validate the full corner quad, source bounds and targets 2026-10-11 01:50:31 +07:00
bflatasticandClaude Opus 5.5 57050b0987 Review #998: one strict anchor parser; build fix for path.appendAnchor
The PR added `checked_anchor_from_json` next to the lenient
`anchor_from_json` and dropped path.rs's import of the latter, which
`path.appendAnchor` still called, so the engine didn't compile.
`anchor_from_json` is now the strict parser itself (handles through
`finite_numbers`), used by path.create, path.setAnchors and
path.appendAnchor alike: the Pen's appended anchor with a malformed
handle fails too instead of losing the handle. Tests: a non-boolean
`closed` and a malformed appended handle change nothing. rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:50:30 +07:00
Nigel Ihza Firdausy 743fe2521e fix(path): remove unused legacy anchor parser import 2026-10-11 01:49:22 +07:00
Nigel Ihza Firdausy 6bf2a42e22 fix(path): reject malformed anchors before creating or replacing geometry 2026-10-11 01:49:22 +07:00
bflatasticandClaude Opus 5.5 93cadc8994 Review #997: one anchor-reference parser, for Reshape area type too
`text.reshapeArea` read its anchors with the lenient `parse_refs`, so a
malformed reference among good ones moved only the good ones. It now
uses `checked_refs` as well, and `parse_refs` (no other user) goes.
Test: a mixed list fails without moving anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:48:17 +07:00
Nigel Ihza Firdausy 2f984f2e7a fix(selection): reject malformed anchor references before selection changes 2026-10-11 01:47:03 +07:00
bflatasticandClaude Opus 5.5 2f458842ae Review #996: rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:46:59 +07:00
Nigel Ihza Firdausy 3b742b6c0c fix(assets): validate all explicit export object ids before collecting 2026-10-11 01:46:24 +07:00
bflatasticandClaude Opus 5.5 de17a00eb2 Review #987: test the next-object stroke with nothing selected; rustfmt
A rejected Stroke panel edit with nothing selected leaves the next
object's stroke as it was; an accepted one sets its weight and dashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:46:22 +07:00
Nigel Ihza Firdausy 059bd82676 fix(stroke): reject malformed dashes and keep defaults atomic 2026-10-11 01:45:19 +07:00
bflatasticandClaude Opus 5.5 6eeabcd742 Review #986: the rect through finite_numbers; rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:45:18 +07:00
Nigel Ihza Firdausy bfbe9e1eb6 fix(cut): reject malformed rectangle cut bounds 2026-10-11 01:44:43 +07:00
bflatasticandClaude Opus 5.5 ac6d72b44a Review #985: one parser for exact number lists; null at is no position
- `finite_numbers::<N>` (cmd/mod.rs) reads an array of exactly N finite
  numbers, nothing dropped or padded; `rect` uses it, and the rect cut,
  Free Distort and anchor handles reuse it in the PRs stacked on this one.
- `at` is parsed once (`at_param`) instead of point_param plus a second
  shape check that indexed the params; `at: null` means no position, as
  null does for the other optional params, and gets a test.
- rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:44:11 +07:00
Nigel Ihza Firdausy 004d015cfe fix(place): reject malformed rectangle and position parameters 2026-10-11 01:42:58 +07:00
bflatasticandClaude Opus 5.5 e860b01ed8 Review #984: rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:36:54 +07:00
Nigel Ihza Firdausy 4c011cf42e fix(paint): preserve new-art defaults when paint edits are rejected 2026-10-11 01:36:17 +07:00
BFlat 6f7f32c64d Merge pull request #1017 from storytold/feat/brush-strokes-effects
Part of gap 2: Effect › Brush Strokes (Accented Edges, Angled Strokes, Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes, Sumi-e)
2026-10-11 01:24:49 +07:00
bflatasticandClaude Opus 5.5 59c890df9e Part of gap 2: Effect › Brush Strokes (Accented Edges, Angled Strokes, Crosshatch, Dark Strokes, Ink Outlines, Spatter, Sprayed Strokes, Sumi-e)
Eight raster effects on the pixel-filter pipeline
(vectorcraft_effects::pixel::brushstrokes), under a new Effect › Brush
Strokes submenu between Blur and Distort in the Raster Effects section:

- Accented Edges (edgeWidth pt 1..14, default 2; edgeBrightness 0..50,
  38; smoothness 1..15, 5): the edges of the softened object painted
  towards white chalk at high brightness or black ink at low brightness;
  Smoothness also leaves the faint edges out. The shape stays as it was.
- Angled Strokes (directionBalance 0..100, 50; strokeLength pt 3..50, 15;
  sharpness 0..10, 3): light areas in right diagonal strokes, dark areas
  in left diagonal ones; 0 makes every stroke a left diagonal, 100 every
  stroke a right diagonal. Sharpness brings detail and bristles back.
- Crosshatch (strokeLength pt 3..50, 9; sharpness 0..20, 6; strength
  1..3, 1): the detail kept under pencil hatching along both diagonals,
  Strength passes of it, the edges roughened.
- Dark Strokes (balance 0..10, 5; blackIntensity 0..10, 6;
  whiteIntensity 0..10, 2): short strokes towards black in the dark
  areas, long strokes towards white in the light areas.
- Ink Outlines (strokeLength pt 1..50, 4; darkIntensity 0..50, 20;
  lightIntensity 0..50, 10): black outlines over the edges, ink hatching
  in the shadows, shadows darkened and highlights lightened.
- Spatter (sprayRadius pt 0..25, 10; smoothness 1..15, 5): each pixel
  shifted by noise up to 0.4 x the radius; Smoothness makes the grains
  larger and smoother.
- Sprayed Strokes (strokeLength pt 0..20, 12; sprayRadius pt 0..25, 7;
  strokeDirection Right Diagonal, Horizontal, Left Diagonal or Vertical):
  strokes along the direction, scattered by up to 0.3 x the radius.
- Sumi-e (strokeWidth pt 3..15, 10; strokePressure 0..15, 2; contrast
  0..40, 16): wet strokes, ink bleeding from the darks along paper
  fibres, more ink with pressure and an S-curve contrast for rich blacks.
  It works in value only: hues and saturation stay, and so does the
  object's shape (no fringe in the transparency).

A stroke averages the colour along a segment through the pixel (16
samples at most, the art softened first when they lie more than a pixel
apart); strokes lie in rows around the object's centre, each row
starting at random and each stroke shifted along itself, with streaked
noise for the bristles. Everything is in document space, so the effects
look the same at any zoom or resolution, move with the object and draw
the same every time; outsets and reaches are exact. On a 2000 x 2000
raster in release the slowest settings take 0.3-2.0 s (Crosshatch at
50 pt with 3 passes the most).

Shared helpers instead of copies: edges::sobel (Glowing Edges now uses
it, unchanged), distort::displace and texture::Tones are pub(super).

Catalogue rows with parameter docs, menu entries, Sprayed Strokes'
direction dropdown, translations (de, es, fr, it, ja, ru, uk, zh-hans,
zh-hant; menu labels in cs and pt-br), tests (parameters and clamping,
outsets and reaches, each filter and option showing, chalk and ink on
the edges only, shadows and rich blacks, Sumi-e keeping the shape and
hues, hatching keeping the tone, strokes smearing along their direction,
Spatter's radius, resolution and move invariance, canvas, multithreaded,
PDF and SVG, the command sweep with junk parameters, the menu) and
ROADMAP.

Behaviour from public documentation only:
https://helpx.adobe.com/photoshop-elements/using/brush-stroke-filters.html
https://www.computerhope.com/jargon/p/photoshop-sprayed-strokes.htm

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:19:26 +07:00
Brandon ThomasandClaude Opus 5.5 d4b0a5479b Progress docs: target-app parity, gaps, alpha gate, readiness by audience (#994)
Progress docs per craftrules standards/progress-docs.md: target-app parity, gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and feature, format, hardware, UI and localization parity docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:11:14 -04:00
BFlat 7989d1345f Merge pull request #846 from alpha-rock/codex/3d-effects
Add live Revolve effect with artboard rotation and lighting gizmos
2026-10-11 00:50:04 +07:00
bflatasticandClaude Opus 5.5 f443dde16f Review: German for Revolve, one row per catalog key, README
The Revolve dialog and gizmo strings in German (the catalog landed after
this branch was written), with Kreiseln and Aussehen umwandeln as the
catalog already names them. Intensity, which main's Texture filters
added meanwhile, is kept once per catalog. README's missing list says
what 3D still lacks beyond the initial Revolve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:04:55 +07:00
alpha-rock c36b6976e3 M9: add live Revolve with artboard rotation and lighting controls 2026-10-10 23:44:46 +07:00
BFlat 01e165af63 Merge pull request #982 from storytold/fix/964-first-frame-watch
#964: start again when the first frame never reaches the screen
2026-10-10 23:40:02 +07:00
bflatasticandClaude Opus 5.5 199a464140 #964: start again when the first frame never reaches the screen
With High Performance chosen on a hybrid laptop, the window's first
frame never reached the screen: no error, no panic, the app stayed in
the background without a window and the log stopped after "rendering
with". The start-up recovery of #502 only saw failures.

A watch thread now gives the first frame 20 seconds from the app's
creation (after the files named at the start opened). When the second
frame hasn't begun by then, so the first was never presented, the app
starts again without that adapter, as it does after a graphics failure,
and this process ends. A window minimized at the start isn't counted.
When the hung processor was chosen in Preferences, the status bar's
note after the restart points to Automatic.

docs/development.md explains it and how to recover from a Graphics
Processor choice that doesn't work; ROADMAP Last updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:38:58 +07:00
BFlat 45516a6a96 Merge pull request #761 from fahrim/mcp-variables
Variables (data merge): text/visibility variables, datasets, panel
2026-10-10 23:35:20 +07:00
bflatasticandClaude Opus 5.5 d0015a496b variables: Window › Variables opens the panel
As Window's other panel items do, and as the reference's Window menu has
it, Window › Variables is the panel itself instead of a submenu of
eighteen commands. The panel menu gains Make Text Dynamic, Make
Visibility Dynamic, Unbind Variable and Delete Variable beside the
bottom bar's buttons, which share one reading of what the selection
allows; every command stays in the command palette. The labels only
the submenu used leave the catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:34:21 +07:00
bflatasticandClaude Opus 5.5 2e07f887bf docs: Variables in the ROADMAP's last-updated list (#761)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:34:21 +07:00
bflatasticandClaude Opus 5.5 500e19680d variables: review fixes for the panel, dialogs and translations
- Dataset and variable names are the user's: the panel's Data Set dropdown and
  the dialogs' name dropdowns show them as they are instead of translating
  them; the dialog's Kind dropdown shows translated kind names.
- Choosing the empty option in a dialog dropdown picked the first name.
- The panel reads the art once per frame for every row's italics, the dialog
  no longer clones the document's variables every frame, and slices are
  matched instead of indexed.
- "No document" and "Define a variable first" go through tl!, and the dialog
  headings Variable Options / Edit Data Set, Text and Visibility have rows in
  every complete catalog; the unused "{name} · {kind} · {count}" row is gone.
- German rows for every Variables string (the catalog predates this branch).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:34:21 +07:00
bflatasticandClaude Opus 5.5 b3fa281282 variables: review fixes for hidden objects, namespaces and agent params
- A visibility variable could hide an object but never show it again: dataset
  application, capture and binding refused any object that wasn't visible
  (`is_editable`), so a row that hid an object left it hidden for good and a
  capture after hiding it in the Layers panel didn't record it. They now use
  `Document::variable_target`, which ignores the object's own visibility
  (locked art and art on hidden or locked layers are still skipped).
- Renaming a variable renamed the active dataset when the two shared a name,
  leaving it pointing at a dataset that doesn't exist.
- `variable.delete` and `dataset.delete` without `names` act on the
  highlighted variable and the active dataset, so Window > Variables > Delete
  Variable / Delete Data Set no longer fail with "missing `names`".
- `ids` is checked like other commands' explicit targets (a non-list no longer
  falls back to the selection, bad ids are errors), names are trimmed and
  capped at 255 characters, and the bind checks are shared by Bind and Make
  Dynamic.
- Make Dynamic's fallback name no longer becomes " 2" for unnamed art.
- `dataset.list` reads the art once for every row's drift check, and
  `Variables::prune` looks names up in a set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:34:21 +07:00