Commit Graph
6034 Commits
Author SHA1 Message Date
aiongg 9997ff0215 ci: run the printps tests under their moved path and fail when none run (#4305)
The module layout moved tests_printps to tests::printps, so the print
workflow's filter matched nothing and the step passed with 0 tests.
2026-10-27 21:09:33 -04:00
aiongg 54c4f82638 Merge pull request #4295 from Jeremy8776/feat/install-scope-policy
Windows installation policy: VectorCraft
2026-10-27 17:16:50 -04:00
Jeremy ddf9845a27 test(installer): cover the compiled folder searches, resolver chains and wizard folder replay
The policy check now reads the compiled AppSearch and RegLocator rows for the
remembered-folder properties (registry root, key, value name and type for both
scopes) and runs the DIR, FOLDER, PATH and legacy exe actions in sequence order
against seeded values, so their precedence and the preset-folder guard cannot
regress. It also replays the wizard folder actions in sequence order (a
remembered folder beats the new-install default, a typed folder beats both) and
requires the machine restore action between the scope page and costing.
2026-10-27 21:13:29 +00:00
skylar taylor-barrick 0051b8af76 Merge pull request #3283 from el-j/fix/compound-path-pen-join
M2.1: allow Pen tool and path.join to continue, close, and join compound paths (#3274, #3276, #3379, #3380)
2026-10-27 15:13:15 -06:00
aiongg 28b5b9249c ci: use storytold/craft-common-actions at the merged installer-policy commit 2026-10-27 20:52:02 +00:00
Jeremy 1440538ab6 fix(installer): check the exact architecture-specific machine folder
The pre-signing check matched any folder named Program Files, so it rejected
a valid MSI when Windows resolves Program Files elsewhere, accepted the 64-bit
root for an x86 package and accepted a different app name. Build the expected
folder from the package architecture's resolved root and the policy name.
2026-10-27 19:08:52 +00:00
skylar 9952b4950c Merge main (8622d0c7) into fix/explicit-join-ends-3283 2026-10-27 12:20:09 -06:00
skylar be49005d5f Merge main (e6d84c9d) into fix/explicit-join-ends-3283 2026-10-27 12:12:21 -06:00
aiongg 8622d0c71c Merge pull request #4359 from Silvertree2010/perf/export-speed
Make SVG export def ids linear instead of quadratic
2026-10-27 13:40:44 -04:00
skylar 1ffc04506c fix(engine): honor explicit ends when joining direct selections 2026-10-27 11:11:36 -06:00
skylar taylor-barrick e6d84c9d60 ci(deps): split Dependabot cargo group into lockstep families (#4223)
Group lockstep crate families into one PR each and batch only patch bumps of everything else, so a crate that needs code changes no longer blocks the rest. No ignore rules; security updates unchanged. open-pull-requests-limit 10.
2026-10-27 09:59:01 -06:00
Jeremy d5aeea632e fix(installer): resolve the wizard scope and folder correctly
Real msiexec runs (per-user and all-users, silent and wizard) found two defects
that the metadata fixtures cannot see:

- "Only for me" published ALLUSERS=2, so FindRelatedProducts treated the run as
  per-machine and skipped the existing per-user copy. An interactive upgrade
  left two registered products and uninstall left files behind. The page now
  leaves ALLUSERS unset for a per-user choice.
- Windows Installer resolves Program Files once, for the context it started in,
  so choosing "Everyone" in the wizard installed into the user profile with a
  machine-wide registration. The wizard now sets the new-install folder itself
  after the choice (Program Files, Program Files (x86) for 32-bit, or the
  per-user Programs folder). Silent installs are unchanged.

check-install-policy.ps1 now fails if either regresses.
2026-10-27 15:32:39 +00:00
aiongg 13d837363d Dropdowns: menus grow back after a search with no matches (#4337)
* chore(deps): pin craft-libs to 62bb0e1d (shared combo box)

* fix(ui-egui): dropdown menus grow back after their contents shrink

Every combo box is craft_ui::ComboBox, whose menu follows its contents'
height while it is open (egui#5225); clippy.toml bans egui::ComboBox.

The font family menu is a craft_ui::combo::Menu under its field, with the
search field and filters in its header and the family rows scrolling under
them, still laid out only in view. The menu keeps to the room on its side
of the field, so the list's minimum height and the popup's room are gone.

* fix(ui-egui): the shortcut import's target picker grows back after a search

Its search field, "No equivalent" and the row's choices are the header of
a craft_ui::combo::Menu, and Keyboard Shortcuts' entries scroll under
them. That was the last menu on the popup path that capped itself at the
room left, so that path and combo's `searchable` flag are gone.

* chore(deps): craft-libs 60d60d48 (dropdown fixes)

* chore(deps): craft-libs 4d7b82f7 (dropdown fixes)

* chore(deps): craft-libs 92d392cf (#387 merged)

* chore(xtask): pdf-deps expects craft-libs 92d392cf
2026-10-27 10:36:58 -04:00
el-j 464a0710b7 Merge remote-tracking branch 'upstream/main' into fix/compound-path-pen-join 2026-10-27 14:33:06 +01:00
Jeremy 2298383f55 docs(installer): say that silent installs are per-user and when the scope page appears 2026-10-27 12:26:56 +00:00
Jeremy 005f5b4d39 docs(installer): note that the 32-bit all-users folder is Program Files (x86); tidy wording 2026-10-27 12:25:21 +00:00
Jeremy 094b228aea docs(installer): describe the per-user default install location and scope 2026-10-27 12:09:04 +00:00
Jeremy 85250cd220 fix(installer): harden install-policy checks and packaging-lint workflow 2026-10-27 12:01:53 +00:00
Jeremy 921426bf56 fix(installer): address scope and ARM64 review feedback 2026-10-27 12:01:53 +00:00
Jeremy 9348aadb9f feat(installer): default to a per-user ArtCraft folder 2026-10-27 12:01:53 +00:00
NetterSilverandClaude Opus 5.5 19d4adb39c Make SVG export def ids linear instead of quadratic
Writer::fresh_id probed prefix-1, prefix-2, ... from 1 on every call,
formatting and hashing each candidate, so writing N gradients, clip
paths or masks cost O(N^2). Ids are never released, so every number
below the last one handed out for a prefix is taken: remember where
the search for each prefix stopped and resume there. The ids written
are the same as before.

examples/still-life.vectorcraft (12k gradients, 6.3 MB SVG) exported
in about 8.6 s (median); it now takes about 0.15 s. Output is byte-identical
for every document in examples/.

Add crates/engine/examples/export_bench.rs to time document.export
on the example documents, and a test pinning the generated id
sequence when object names already take some of the numbers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:52:22 +01:00
BFlat 443b31b13d Merge pull request #4301 from ham9zah/fix/appearance-mixed-selection
Appearance: a mixed selection lists the attributes its objects share (#4174)
2026-10-27 15:10:31 +07:00
BFlat bd50cf4c35 Merge pull request #4282 from dotCooCoo/fix/window-frame-auto-hide-taskbar
Windows: a maximized window stops a pixel short of an auto-hidden taskbar
2026-10-27 15:10:15 +07:00
BFlat b024896ca0 Merge pull request #4279 from dotCooCoo/fix/window-frame-top-taskbar
Windows: a maximized window stays clear of a taskbar on the top or a side
2026-10-27 15:09:59 +07:00
BFlat dcb704972b Merge pull request #4275 from dotCooCoo/fix/threaded-outlines-parity-source
Docs: cite the public thread help for outlining a threaded frame
2026-10-27 15:09:48 +07:00
BFlat 3965fdf319 Merge pull request #4274 from nrq6993-a11y/stream/vc-feat3-g2-scribble-settings-presets
G2: Scribble effect Settings presets
2026-10-27 15:09:33 +07:00
BFlat c3df88b724 Merge pull request #4195 from dotCooCoo/fix/new-brush-keeps-captured-art
Brushes: New Brush makes the brush from the art its options opened with
2026-10-27 15:09:22 +07:00
BFlat 32d061db7f Merge pull request #4309 from nrq6993-a11y/stream/vc-feat3-g4-mixed-optical-margin
G4: Optical margin menu uses shared text flag
2026-10-27 15:09:07 +07:00
BFlat 355dcf53d6 Merge pull request #4288 from Silvertree2010/fix/h2791-mcp-resource-uri-percent-decoder
Only treat % plus two hex digits as an escape in MCP resource URIs
2026-10-27 15:08:50 +07:00
BFlat 8d854bda27 Merge pull request #4304 from Silvertree2010/fix/h2808-shape-polygon-and-shape-star-sil
Accept whole-number floats and reject invalid counts for polygon, star and spiral
2026-10-27 15:08:35 +07:00
BFlat b35cc1bdd4 Merge pull request #4308 from rahul05ranjan/r18-proxy-cap
fix(doc): decode the linked-image proxy within MAX_RASTER_ALLOC (#3597)
2026-10-27 15:07:41 +07:00
BFlat 06ff5201cb Merge pull request #4310 from rahul05ranjan/r18-json-cap
fix(format): cap a compressed file's JSON at 256 MB on wasm32 (#3587)
2026-10-27 15:07:27 +07:00
ham9zah 0365cf3ae3 Appearance: shared rows map one by one, and effect dialogs edit each copy (#4174)
Review follow-ups:

- items_per_target maps each requested row on its own. Rows deleted or
  duplicated together, one shared and one not, fell back to the literal
  indices in every object, so the other objects could lose the wrong
  items. The first object takes its own rows; each other object takes
  its copies of the shared ones only.
- effect.dialog takes `aligned` (the panel passes it on a mixed
  selection's shared effect row), and its OK and preview run
  effect.setParams with it, so the dialog edits each object's own copy
  of the effect instead of the first object's index in every object.

Tests: removing a shared stroke with an unshared fill leaves the other
object's fills; an aligned dialog's command carries `aligned`.
2026-10-27 14:36:13 +07:00
ham9zah 8305ccf998 Appearance: a mixed selection lists the attributes its objects share (#4174)
With several objects selected whose appearances differ in anything (two
circles whose fills differ but whose stroke and effect are the same),
the Appearance panel showed only "Mixed Appearances": no stroke, effect
or opacity row, so attributes the objects share couldn't be edited
together. It now lists what they share, as the issue describes:

- `vectorcraft_doc::appearance::SharedStack` (with `align`, a stacking-
  order longest-common-subsequence match) gives the fills, strokes and
  object-level effects every object has an equal copy of, and where each
  is in every object's own stack.
- The panel's object row names the objects' common kind ("Path",
  "Ellipse"; "Mixed Objects" only when kinds differ, as the Control bar
  does), with an italic "Mixed Appearances" row under it when they
  differ, then only the shared rows with their usual controls. The
  Opacity row reads "Mixed" when opacity or blend mode differ (an edit
  sets them all). The object row shows no fill chip when the fills
  differ. Rows aren't dragged in a mixed selection: where a row would go
  in each of several different stacks isn't one place.
- The engine maps a shared row to each object's own item: the active
  item (a row of the first selected object's stack) always does, so the
  Color, Stroke and Transparency panels edit every object's matching
  item, and the item and effect commands do with `aligned: true`
  (appearance.setItem / removeItem / duplicateItem, effect.remove /
  duplicate / setParams / lightingPreset, transparency.set), each as
  one undo step. moveItem and effect.move refuse aligned rows of
  differing stacks. Without `aligned`, explicit indices keep their
  meaning for single objects and scripts.
- "Mixed" is added to every catalog.

Tests: the shared stack of the issue's case, of a stroke at another
index, of nothing alike and of equal stacks, and that matches never
cross; editing the shared stroke edits both strokes (at index 1 and 2)
in one undo step that restores both, also through stroke.set on the
active row; removing a shared effect and adding a fill reach both, and
reordering differing stacks is refused; the panel lists kind, note,
Stroke, Feather and Opacity, not Fill, the full stack for alike objects
and "Mixed Objects" for a path and type. The existing object-row test
now expects the kind for two rectangles and the shared rows when their
opacity differs.
2026-10-27 14:36:13 +07:00
dotCooCooandHiggs32584 52c92cb419 Windows: a maximized window stops a pixel short of an auto-hidden taskbar
An auto-hidden taskbar reserves no work area, so the guard that keeps
the custom title bar's window borderless left a maximize covering the
whole monitor. The shell treats a caption-less window that covers its
monitor as a full-screen app, and in PhotoCraft, which has the same
guard, the hidden taskbar then did not show when the pointer reached
its edge (storytold/photocraft#4845).

While a maximized window covers its whole monitor, the guard now finds
the taskbars (the Shell_TrayWnd and Shell_SecondaryTrayWnd windows),
takes the monitor edge nearest each one's center, and stops the window
one pixel short of the monitor on each of those edges where the work
area reaches the monitor's edge. A taskbar that reserves a work area
is still cleared by the move into the work area. This ports
Higgs32584's fix in PhotoCraft (storytold/photocraft#6878).

Docs: docs/target-app-parity.md.

Co-authored-by: Higgs32584 <mhiggins217@gmail.com>
2026-10-27 14:36:12 +07:00
dotCooCooandFredApps a5f0e6ba36 Windows: a maximized window stays clear of a taskbar on the top or a side
With the taskbar on the top edge, a maximize, a restore from the
taskbar or a drag to the top of the screen showed a classic title bar
above the app bar (#3242, #3723, #2072). The guard that keeps the
custom title bar's window borderless trimmed only the bottom of a
parked maximize to the work area, so with the taskbar on the top or a
side the window still covered it, and the strip between the window's
edge and the client area, which winit keeps on the work area, was
drawn as an old-style caption.

The guard now moves a parked maximize inside the work area on every
edge, keeping the resize border it was parked with, which it reads
from an edge without a taskbar. A rect it already moved, a dragged or
snapped window and a monitor with no reserved taskbar are left alone.
The move uses SWP_FRAMECHANGED and SWP_NOCOPYBITS and invalidates the
window, so the whole window is drawn again, and the style strip uses
SWP_NOCOPYBITS too. This ports FredApps's fix in PhotoCraft
(storytold/photocraft#5237).

Docs: docs/target-app-parity.md.

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-10-27 14:36:12 +07:00
dotCooCoo a0d11d0da6 Docs: cite the public thread help for outlining a threaded frame
The parity doc's line on Create Outlines, Expand and Expand Appearance
on a frame of threaded text gave no source. It now links the public
help pages on creating and removing text threads, and says that they do
not describe outlining a threaded frame, so the handling is VectorCraft's
own behavior.
2026-10-27 14:36:12 +07:00
nrq6993-a11y dfec712c2d G2: Scribble effect Settings presets
Squashed from #4274 onto main.
2026-10-27 14:36:12 +07:00
dotCooCoo ca60c8e8a7 Brushes: New Brush makes the brush from the art its options opened with
OK in a new scatter, art or pattern brush's Brush Options ran brush.new
without the art the dialog had captured for its preview, so brush.new
read the selection again. A selection changed while the dialog was open
gave the brush other art than the preview showed, and a cleared
selection made OK fail. OK now passes the captured art (the side tile
for a pattern brush) to brush.new.
2026-10-27 14:36:12 +07:00
nrq6993-a11y 678cff6707 G4: Optical margin menu uses shared text flag
Squashed from #4309 onto main.
2026-10-27 14:36:12 +07:00
NetterSilverandClaude Haiku 5.5 76e0e5b0ac Only treat % plus two hex digits as an escape in MCP resource URIs
Found while testing crates/mcp/src/resources.rs:169 (decode)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 14:36:12 +07:00
NetterSilverandClaude Haiku 5.5 23f0d323b0 Accept whole-number floats and reject invalid counts for polygon, star and spiral
Found while testing crates/engine/src/cmd/create.rs:344 (polygon) and :358 (star; shape.spiral `segments` at :507 reads the same way)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 14:36:12 +07:00
Rahulandrahul05ranjan 6213302260 fix(doc): decode the linked-image proxy within MAX_RASTER_ALLOC (#3597)
proxy_png decoded with image's default limits and no header check, while
every other decode path in the project uses MAX_RASTER_ALLOC counted as
RGBA. The header now decides first, and the decoder gets the same budget,
so an image too large to draw gets no preview by header alone, and a
large-but-in-cap image the app itself can open now gets its preview.

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
2026-10-27 14:36:12 +07:00
bflatastic d6331bec1c Format: repeat_n in the JSON cap test (clippy manual_repeat_n) 2026-10-27 14:36:12 +07:00
Rahulandrahul05ranjan 36cc081316 fix(format): cap a compressed file's JSON at 256 MB on wasm32 (#3587)
MAX_JSON was 1 GiB on every target, but on wasm32 the 4 GiB address space
also holds the document the JSON deserializes into, several times its size.
The cap is now a quarter of the native one there, mirroring MAX_BLOBS,
and Unpacked::within makes the cap exercisable wherever a test runs.

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
2026-10-27 14:32:54 +07:00
Rahulandrahul05ranjan 10dfb8b261 fix(format): cap a compressed file's JSON at 256 MB on wasm32 (#3587)
MAX_JSON was 1 GiB on every target, but on wasm32 the 4 GiB address space
also holds the document the JSON deserializes into, several times its size.
The cap is now a quarter of the native one there, mirroring MAX_BLOBS,
and Unpacked::within makes the cap exercisable wherever a test runs.

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
2026-10-27 14:32:54 +07:00
aiongg eb0e99a553 Merge pull request #4294 from aiongg/layout
refactor: shared module layout (craft-contrib#20)
2026-10-26 21:31:59 -04:00
skylar taylor-barrick 5815205324 Merge pull request #4286 from storytold/fix/nextest-0.9.150
ci: require nextest 0.9.150
2026-10-26 18:08:53 -06:00
aiongg e724228e25 docs: update source paths for the moved files 2026-10-26 22:01:25 +00:00
aiongg fafab0d822 ci: follow tests_printps.rs to tests/printps.rs in the print workflow path filters 2026-10-26 22:01:25 +00:00