Commit Graph
3649 Commits
Author SHA1 Message Date
NetterSilverandClaude Opus 5.5 bcbc8a1713 Expand the stroke of stroked type into filled outlines
Fixes #4306

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:57:34 +07:00
dotCooCoo 6026772765 Fix #3773: Offset Path offsets a path whose ends meet as a closed shape
Offset Path outlined an open path on both sides, so a shape whose last
anchor sits on its first came out as a ring with a hole. Such a path is
now offset as a closed shape: its last anchor merges into its first,
which takes the last anchor's in-handle, with the same 1e-6 test that
Object › Path › Join uses for one path (crates/engine/src/cmd/path.rs).
The Offset Path effect calls the same function.
2026-10-29 09:57:34 +07:00
NetterSilverandClaude Opus 5.5 b6422e5ba1 Keep compound path holes when using the Eraser and Knife
Fixes #4495

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:57:34 +07:00
el-j c96f0c30f7 perf(ui-egui): eliminate zero-filling allocation on canvas texture upload in color_image (#4504)
- Replace vec![Color32::TRANSPARENT; N] zero-initialization with direct single-copy bytemuck::cast_slice(&img.pixels).to_vec() in color_image.
- Eliminates redundant zero-filling of ~20.7 MB buffer on every canvas frame render on Retina displays, saving memory bandwidth and allocation overhead.
- Fallback preserves transparent image for undersized or mismatched pixel buffers.

Fixes #4504.
2026-10-29 09:57:34 +07:00
bflatastic ace60bd542 Edit Colors: import f64_req and check_numbers in colorcmds.rs (#4299 made the imports explicit) 2026-10-29 09:57:34 +07:00
dotCooCoo 8c0750e848 Edit Colors: Saturate without an intensity is an error instead of a pass at 0
edit.colors.saturate's params text names intensity as required, but a
call without it, or with a string such as "40", read the intensity as
0 and still ran Saturate. It changed no visible color but recorded a
Saturate undo step.

edit.colors.saturate now reads intensity with f64_req, as shape.ellipse
reads its box. A missing, null or non-number intensity is the error
"missing number `intensity`", which changes nothing and records no undo
step. A number outside -100..100 still counts as its nearest end, and
the params text says so.

Saturate returns a color whose saturation stays the same, as at an
intensity of 0, as it was. The HSB round trip rewrote most such colors
in their last bit, so they counted as changed and lost their swatch
link.

In the same file, edit.colors.adjustBalance read a channel that is not
a number as 0, and color.harmony read steps or amount that is not a
number as its default. Both now refuse it with check_numbers, as the
commands docs/mcp.md lists for #1952 do. A null is still read as a key
left out.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 09:57:33 +07:00
bflatastic 49509be9a8 Layers: import switch_or in layer.rs and layerpanel.rs (#4299 made the imports explicit) 2026-10-29 09:57:33 +07:00
dotCooCoo 4519346cfb Layers: the Layers panel's commands refuse a boolean given as text
layer.new, layer.selectAll, layer.target, layer.move, layer.template,
layer.pasteRemembersLayers and layer.releaseToLayers read their on/off
params with bool_or or as_bool, which falls back to a default for a
value that is not true or false. layer.new {"top": "true"} added the
layer above the current one instead of on top, layer.template
{"on": "false"} and layer.pasteRemembersLayers {"on": "false"} turned
the option on when it was off, layer.move {"copy": "true"} moved the
rows instead of copying them, layer.selectAll and layer.target with
"add": "true" replaced the selection, and layer.releaseToLayers
{"build": "true"} released the objects without building up copies.

These commands now fail with "`<key>` must be true or false" for a
value that is not true, false or null, as the artboard and Object menu
commands do, and leave the document, the selection, the highlighted
rows and the undo history as they were. layer.newSublayer, which takes
layer.new's options, refuses such a top too. A null is read as a key
left out.

docs/mcp.md also lists showCenterMark, showCrossHairs and
showVideoSafeAreas among the keys artboard.new and artboard.setProps
refuse in this way, as they already did.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 09:57:33 +07:00
dotCooCoo 1deb1ec152 Artboards: artboard.new and artboard.setProps refuse a number or name of the wrong type
artboard.setProps refused an x, y, width or height given as text, but
artboard.new read such a value as the key left out: {"x": "10"} added
an artboard at the default position and recorded an undo step. Both
commands read a name that is not a string, such as 5, as no name, so
artboard.new gave the default name and artboard.setProps kept the old
one.

artboard.new now refuses an x, y, width or height that is not a number
with "`<key>` must be a number, not <value>", the message
artboard.setProps gives, and both commands refuse such a name with
"`name` must be a string", for each entry of artboard.setProps'
artboards too. They refuse it before they change anything. A null is
still read as the key left out.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 09:57:33 +07:00
NetterSilverandClaude Haiku 5.5 ad43722a56 Accept whole-number floats as grid divider counts
Found while testing crates/engine/src/cmd/create.rs:584 (dividers)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 09:57:33 +07:00
bflatastic cfe21231c8 SVG import: import NodeId and SvgError in importer.rs (#4299 made its imports explicit) 2026-10-29 09:57:33 +07:00
el-j 39341ef4c8 Fix #3564: report TooManyImages error when nested SVG image cap is reached 2026-10-29 09:57:33 +07:00
el-j b65fb23338 fix(svg): cap converted objects and nested images (#3564) 2026-10-29 09:57:33 +07:00
Don Omondi def9e0f08e Blend: nested blends keep to a step budget (#3579)
A blend whose keys are blends draws each of its steps as a copy of a key,
and that copy makes its own steps when it is drawn, so step counts capped
per pair multiplied with nesting: five levels of 15 steps were 1.3 million
steps from a 23 KB file, 3.4 GB to export.

A blend now makes at most 100,000 steps in all (MAX_BLEND_STEPS), counting
the steps of the blends inside its keys and steps. Past the budget each pair
of keys keeps the same share of its steps; a copy of a blend spaced by
distance counts the most steps its spacing can make, since scaling it up
adds steps. Blends within the budget draw every step as before.
2026-10-29 09:57:33 +07:00
Max MittelstädtandGPT-6-Luna c714797e99 Reject fractional DXF integer values
Found while testing crates/cad/src/import/reader.rs:69

Co-Authored-By: GPT-6-Luna <noreply@openai.com>
2026-10-29 08:45:52 +07:00
NetterSilverandClaude Haiku 5.5 ddd017eb0a Reject a sign after # in EPS PostScript radix numbers
Found while testing crates/eps/src/import/lex.rs:287-289 (number)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:45:39 +07:00
NetterSilverandClaude Haiku 5.5 aca98ffe79 Reject non-hex characters in EPS uni/u glyph names
Found while testing crates/eps/src/import/text.rs:501-502 (glyph_char)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:45:25 +07:00
NetterSilverandClaude Haiku 5.5 de6b14b541 Accept CRLF lines of exactly the maximum length in the MCP reader
Found while testing crates/mcp/src/server.rs:180-205 (read_line_capped)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:45:12 +07:00
NetterSilverandClaude Haiku 5.5 66498b9740 Reject non-hex digits in RTF \'XX escapes
Found while testing crates/engine/src/cmd/place/rtf.rs:111

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:44:57 +07:00
NetterSilverandClaude Haiku 5.5 26f9b7f80c Reject non-hex characters in Image Trace ignoreColor
Found while testing crates/ui-egui/src/panels/image_trace.rs:28-34 (ignore_color)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:44:45 +07:00
NetterSilverandClaude Haiku 5.5 c2fb35b244 Fix ColorKey Display overflow on huge negative Lab a/b
Found while testing crates/color/src/recolor.rs:72 (Display for ColorKey)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-29 08:44:39 +07:00
NetterSilverandClaude Opus 5.5 4c4113096c Seed PDF encryption keys from the OS random source
Fixes #3605

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:44:36 +07:00
Dylan M. Taylor 484d25582c Merge remote-tracking branch 'origin/main' into pr-4299-ff 2026-10-28 17:20:12 -04:00
Dylan M. Taylor 86c81f21d2 Restore RTL Mojikumi condition, dropped layout comments and xtask root
- flow.rs: an opening bracket starting a wrapped line is set flush unless the paragraph is
  right to left, as before the split (it had become !vertical, so vertical text with
  LineEndHalf lost the flush and RTL paragraphs gained it). PlacementContext carries rtl.
- flow.rs, ruby.rs: put back the comments the split dropped (JLREQ, burasagari, Optical
  Margin Alignment, kashidas, ruby phases).
- xtask root(): the parent directory, not .../xtask/..
2026-10-28 17:20:12 -04:00
Dylan M. Taylor 12414aa9f6 Make PDF export comparison deterministic 2026-10-28 19:53:43 +00:00
Dylan M. Taylor e6da628e56 Simplify application integration tests 2026-10-28 16:44:19 +00:00
Dylan M. Taylor 55dddf6adf Extract UI event and rendering helpers 2026-10-28 16:44:17 +00:00
Dylan M. Taylor 0b821b3c54 Extract engine command and state helpers 2026-10-28 16:44:14 +00:00
Dylan M. Taylor 7043ef6f3d Extract geometry command helpers 2026-10-28 16:44:11 +00:00
Dylan M. Taylor 90ef99cb2c Simplify file import and export checks 2026-10-28 16:44:05 +00:00
Dylan M. Taylor 62588fd080 Separate selection tool pointer phases and clarify imports 2026-10-28 05:03:13 +00:00
Dylan M. Taylor 7e44df55a9 Make renderer and SVG module dependencies explicit 2026-10-28 05:03:00 +00:00
Dylan M. Taylor 317d270823 Clarify PDF import stages and module dependencies 2026-10-28 05:02:46 +00:00
Dylan M. Taylor 89d538e40c Separate metafile record parsing into focused handlers 2026-10-28 05:02:26 +00:00
Dylan M. Taylor a9e82efcf0 Clarify EPS import and interpreter stages for strict Clippy 2026-10-28 04:52:26 +00:00
Dylan M. Taylor e1bc6b235c Clarify effects dependencies and split parameter checks 2026-10-28 04:52:07 +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
Dylan M. Taylor 0e2815629f refactor(text): split flow and ruby layout phases 2026-10-27 17:47:12 +00:00
Dylan M. Taylor dec8b90e3a refactor(text): clarify line adjustment inputs 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 542a5ae58c refactor(pathops): extract planar sweep graph builder 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 7b05e55a69 refactor(trace): separate graph construction and quantization 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 3d0188a5bc refactor(doc): name text model dependencies explicitly 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 010979864a refactor(doc): make live shape imports explicit 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 4accdf6b00 refactor(doc): clarify appearance and document dependencies 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 951127f585 refactor(affinity): replace model globs with explicit imports 2026-10-27 17:47:12 +00:00
Dylan M. Taylor 8b2439678b refactor(scriptcheck): simplify lexer imports and state 2026-10-27 17:47:12 +00: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
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