Commit Graph
4753 Commits
Author SHA1 Message Date
dotCooCoo 5f6c7b8da9 PDF export: a 16-bit PNG is written at 8 bits for PDF 1.3 and 1.4 instead of failing the export
When the Compression settings keep a PNG as it is, the PNG goes to
the PDF writer unchanged, and the writer refuses images of 16 bits a
sample below PDF 1.5. Saving a document with a placed 16-bit PNG as
PDF 1.4, or as a .ai file at 1.4, failed with "PDF writer error:
SixteenBitImage(...)" and wrote nothing. PDF 1.3 and PDF/X-3 failed
the same way for an opaque 16-bit PNG, and PDF/X-1a failed for a
16-bit gray PNG.

In PDF 1.3 and 1.4 files, such a PNG is now decoded and encoded again
at 8 bits a sample, with the same color type and ICC profile, before
the writer reads it. From PDF 1.5 on, it keeps its 16 bits. A 16-bit
PNG whose pixel data can't be decoded is left out with the note "an
image couldn't be decoded and is missing from the picture".

Docs: docs/mcp.md (PDF options).
2026-10-22 05:57:11 +07:00
BFlat 14a70449f7 Merge pull request #3483 from nrq6993-a11y/stream/vc-feat1-g11-guide-align-artboard-3463
G11: Align panel moves ruler guides to artboard (#3463)
2026-10-22 05:28:22 +07:00
Cursor Agentandnrq6993-a11y c8082facb1 G11: Align panel moves ruler guides to artboard (#3463)
## Summary
object.align now moves selected ruler guides when aligning to the artboard,
matching Illustrator and the existing Distribute behaviour. Guide-only
selection can run align; the Align panel enables its buttons when only
guides are selected. Guides still stay put when objects are in the selection
and Align To is Selection; key-guide behaviour is unchanged.

## Tests
- engine tests_keyguide: guides_selected_alone_align_to_artboard; updated
  selected_guides_align_to_a_clicked_key_object for artboard align
- ui-egui align panel: the_align_buttons_align_guides_selected_alone_to_artboard

Closes storytold/vectorcraft#3463

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 05:20:10 +07:00
BFlat 430741f074 Merge pull request #3481 from dotCooCoo/fix/save-as-extension-compare-ignores-case
Save As: the suggested extension typed in another case gets the picked type's
2026-10-22 05:19:59 +07:00
dotCooCoo bd9a508d49 Save As: the suggested extension typed in another case gets the picked type's
On Linux and the BSDs, where the save dialog reports the file type
picked in it, a name that still ends in the suggested name's extension
gets the picked type's extension. The comparison was case-sensitive,
so Untitled-1.VECTORCRAFT with "PDF-compatible .ai" picked was saved
as a native file named Untitled-1.VECTORCRAFT instead of Untitled-1.ai.

with_picked_type now compares the lower-case extensions that
fileio::extension gives. A name typed with the picked type's own
extension in another case (a.AI with .ai picked) stays as typed.

This follows up #3372.

Docs: docs/target-app-parity.md.
2026-10-22 05:09:55 +07:00
BFlat b15230bfb5 Merge pull request #3461 from lehni/update/canvas-partial-redraw
Canvas: an edit redraws only the area it changed
2026-10-22 05:09:38 +07:00
BFlat 15434b6db4 Merge pull request #2539 from vangel76/feat/1124-blend-easing
Blend: Ease In / Ease Out and separate Color Ease in Blend Options (#1124)
2026-10-22 04:50:42 +07:00
Jürg Lehni ede08590a0 Canvas: an edit redraws only the area it changed
Wide effect rasters cropped to the frame also serve parts of it.
2026-10-22 04:45:43 +07:00
bflatastic 92f295d2a2 Blend: Ease In / Ease Out and separate Color Ease in Blend Options (#1124)
Squashed from #2539 onto main.
2026-10-22 04:40:10 +07:00
BFlat cc42a333b7 Merge pull request #3477 from dotCooCoo/fix/ruby-tests-with-ci-fonts
Type: the vertical ruby test passes with craft-fonts' Shippori Mincho
2026-10-22 04:39:15 +07:00
dotCooCoo 95f503367f Type: the vertical ruby test passes with craft-fonts' Shippori Mincho
tests_ruby::vertical_ruby_is_upright_to_the_right_of_the_column
checked that no reading glyph is more than 1 pt wider than tall. With
craft-fonts in the build, the kana come from Shippori Mincho, whose か
is 8.24 pt wide and 7.22 pt tall at 10 pt. The test failed on that
glyph although it stands upright. FreeBSD CI, which builds with
craft-fonts at a71c20e3, fails it on every branch since 14f804cd. It
also fails on Windows with that ref or an older craft-fonts checkout.

The test now compares each reading glyph's ink with its own outline at
10 pt. The same width and height mean the glyph is upright; a swapped
width and height mean it lies on its side. It also requires one
reading glyph whose outline is not square.
2026-10-22 04:34:32 +07:00
BFlat a339433c4b Merge pull request #3436 from dotCooCoo/feat/character-direction
Character: Character Direction sets the selected characters left to right or right to left
2026-10-22 04:28:48 +07:00
bflatastic 34cde7c3db Character: Character Direction sets the selected characters left to right or right to left
Squashed from #3436 onto main.
2026-10-22 04:18:35 +07:00
BFlat 0ac1f133b0 Merge pull request #3281 from gorkematlyn/upstream-ui8
UI.8: collapse dock groups to their tabs
2026-10-22 04:13:54 +07:00
bflatastic b3268a829d UI.8: collapse dock groups to their tabs
Squashed from #3281 onto main.
2026-10-22 04:07:25 +07:00
BFlat e99dea21ff Merge pull request #3280 from gorkematlyn/upstream-ui6
UI.6: dock panels into any dock group
2026-10-22 03:47:30 +07:00
BFlat 85d5b10350 Merge pull request #3279 from gorkematlyn/upstream-ui7
UI.7: workspaces keep their layout changes
2026-10-22 03:47:14 +07:00
bflatastic 9cda8452ab UI.6: dock panels into any dock group
Squashed from #3280 onto main.
2026-10-22 03:40:36 +07:00
gorkematlynandClaude Opus 5.5 d6d91c0954 UI.7: match workspace names whatever their case
find_saved matched names case-insensitively but save_as, remember and
switch compared them exactly: "Mine" saved over "mine" made a second
workspace, and changes kept as "Mine" didn't come back when switching
to "mine". save_as now replaces a user workspace of the name in any
case, remembered layouts are kept under the saved spelling and looked
up whatever the case, and sanitized maps remembered layouts to the
saved spelling and keeps one per workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 e3e761fe32 UI.7: doc comments on the workspace tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 81de0f6fbf UI.7: keep the newest remembered layout when the list is full
remember() pushed the layout being left and then truncated the list to
64, so with 64 workspaces already remembered it dropped the entry it
had just pushed and the changes were lost. Drop the oldest entries
instead; a test fills the list and checks the last one left survives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
gorkematlynandClaude Opus 5.5 4308821285 UI.7: workspaces keep their layout changes
A workspace remembers the changes made in it: switching away keeps them
(UiState::workspace_changes, kept with the preferences), switching back
restores them, and Reset <name> returns to the saved layout. Saving a
workspace starts it with no changes; renaming keeps them, deleting drops
them, and deleting the current workspace shows Essentials as it was
left. Saved preferences recover a damaged remembered layout instead of
losing the whole file.

Split from #2965 as a reviewer asked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcHisW1vt6pkVPYbzL6Cpg
2026-10-22 03:40:18 +07:00
BFlat 9471f92135 Merge pull request #3466 from mockydevs/fix/eyedropper-selected-text
Fix Eyedropper styling for highlighted text ranges
2026-10-22 03:12:19 +07:00
BFlat 1c9edd9cca Merge pull request #2526 from vangel76/feat/2523-shape-builder-gap-detection
Shape Builder: Gap Detection and Tool Options (#2523)
2026-10-22 03:03:45 +07:00
Don Omondi a3b2b18cb0 M3: preserve highlighted Eyedropper ranges and reject incompatible transparency 2026-10-22 02:58:48 +07:00
Dylan M. Taylor 0f7156169b ci: add sonar-project.properties to use CI-based analysis
Presence of this file marks the project ineligible for SonarCloud Automatic
Analysis, resolving the CI-vs-automatic-analysis conflict.
2026-10-21 15:56:13 -04:00
bflatastic 10a178f64a Shape Builder: Gap Detection and Tool Options (#2523)
Squashed from #2526 onto main.
2026-10-22 02:53:17 +07:00
Dylan M. Taylor a4c21343bb ci: add SonarCloud scan via shared reusable workflow
Calls storytold/craft-common-actions/.github/workflows/sonarcloud.yml@main
with secrets: inherit. Adds SonarCloud badge to README where missing and
removes the redundant sonar-project.properties (config now passed by the
reusable workflow).
2026-10-21 15:47:07 -04:00
BFlat 8a48680ad2 Merge pull request #3457 from nrq6993-a11y/stream/vc-issue-3446-expand-stroke-round-caps
Expand stroke: compact plain stroke spines before outlining
2026-10-22 02:31:43 +07:00
bflatastic dd2f5da98c Expand stroke: compact plain stroke spines before outlining
Squashed from #3457 onto main.
2026-10-22 02:21:59 +07:00
BFlat 19c7d61f8a Merge pull request #3460 from dotCooCoo/fix/live-paint-tools-skip-hidden-faces
Live Paint: the Live Paint tools and livePaint.fill skip hidden faces
2026-10-22 02:12:20 +07:00
BFlat 9effb4e44e Merge pull request #2520 from vangel76/fix/2170-recolor-model
Recolor: recolor.apply takes a model option for the new colour's model (#2170)
2026-10-22 02:12:09 +07:00
dotCooCoo 4bd55029e8 Live Paint: the Live Paint tools and livePaint.fill skip hidden faces
A face hidden on its own (for example with Object > Hide after Live
Paint Selection picks it) while its Live Paint group stays visible was
still highlighted, selected by Live Paint Selection and filled by the
Live Paint Bucket, and it kept the face of a group behind it from being
picked.

live_paint_at and lp_part_at now take the front-most face that is not
hidden (visible_face_at). A point on a hidden face falls through to the
visible face of a group behind it; where there is none, an edge pick
takes the nearest visible edge as it does outside the faces.
livePaint.fill also skips hidden faces. With group, a point on a hidden
face is an error. With ids, it fills the face there of another Live
Paint group among the objects, or else fails and does not merge the
group.

Docs: docs/mcp.md.
2026-10-22 02:01:58 +07:00
bflatastic 62776d5f46 Recolor: recolor.apply takes a model option for the new colour's model (#2170)
Squashed from #2520 onto main.
2026-10-22 02:01:57 +07:00
BFlat 44104b67ca Merge pull request #3456 from nrq6993-a11y/stream/vc-featD-g4-snap-to-glyph-parity
G4: Mark Snap to Glyph done in parity docs and test the menu toggle
2026-10-22 01:35:37 +07:00
BFlat e2d75c7ba6 Merge pull request #3174 from KaboomFox/p8-filter-effects
Plug-ins: filters read and set effects and stroke styles (G17)
2026-10-22 01:35:21 +07:00
Cursor Agentandnrq6993-a11y 59f4b753dd G4: mark Snap to Glyph done in parity docs and test the menu toggle
## Summary
Aligns parity checklists with shipped View › Snap to Glyph behaviour (#3124):
when Smart Guides are on, drawing tools snap to live-text baselines and glyph
bounds via `view.snapToGlyph`. Adds a headless test that `view.snapToGlyph`
toggles the UI view flag like Illustrator’s menu item.

## Tests
- `vectorcraft-ui-egui`: `snap_to_glyph_menu_command_toggles_the_view_flag`
- Existing `tools::text_tests::snap_to_glyph_lines_up_new_point_type_with_a_baseline`

Part of gap G4

Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
2026-10-22 01:25:51 +07:00
Louise FoxandClaude Opus 5.5 8bc117eb8b Plug-ins: doc comments for the functions the filter changes touch
The docstring check of the review counts the functions a pull request
touches: effect.apply, effect.setParams, plugin.run, the line cap
name, the reader of an output object and seven of the object tests had
no doc comment. Each now says what it does or checks; the join and cap
names get one each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
2026-10-22 01:25:51 +07:00
Louise FoxandClaude Opus 5.5 78105cc695 Plug-ins: filters read and set effects and stroke styles (G17)
A filter could reshape and repaint objects, but not set the stroke's
join, cap or miter limit, nor the effects an object's appearance holds.
A tool that prepares objects for a live effect (a sheet of samples,
each with the effect at its own settings) had to leave the user to
apply the effect to each object by hand.

- Each input stroke has its join, cap and miterLimit beside its paint
  and width (live effects get the same, through the shared encoder),
  and each object its own effect records, {id, params, visible}.
- An output stroke may set them (miter limit clamped to 1-500), and an
  output object's "effects" replaces its own effects.
- The host admits each record as effect.apply does: an effect that
  effect.list lists or an installed live-effect plug-in, parameters it
  takes (filled in to their defaults; a plug-in's checked against its
  manifest), one 3D effect that fits the object (its fills' and
  strokes' own effects counted), and the texture of an effect with
  Load Texture (Glass, Texturizer) as the effect stores it, never a
  file to read. A record the object already had stays as
  it is, so a filter that hands its input back changes nothing. One
  refused record refuses the whole output and the document stays as
  it was.

The plug-ins crate checks the records' form; which effects exist is the
engine's to say (objects::AdmitEffects, engine plugin::admit_effects).
effects::validate_three_d is the one check of whether a 3D effect fits
an object, for effect.apply, effect.setParams and the filters.

A path handed back as it was now stays the live shape it was: write()
dropped a live rectangle's or ellipse's parameters whenever the output
held a path, changed or not, so a filter that returned its input
turned a live rectangle into a plain path.

objects/tests.rs checks the round trip, stroke styles on existing and
new strokes, the host's refusal, the bad forms refused, and a live
rectangle handed back unchanged (a plain path before the fix);
tests_plugins.rs runs filters that set a built-in and a plug-in effect,
an echo that changes nothing, and six refused outputs.
CRAFT_PLUGIN_FRAME_WASM=<folder> saves a test filter to try in the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
2026-10-22 01:25:50 +07:00
BFlat ff021918a6 Merge pull request #3096 from nrq6993-a11y/stream/vc-feat3-g2-artistic-fresco
G2: Effect › Artistic › Fresco raster filter
2026-10-22 01:25:22 +07:00
BFlat 45f806d307 Merge pull request #3010 from nrq6993-a11y/stream/vc-feat1-g2-sketch-torn-edges
G2: Effect › Sketch › Torn Edges raster filter
2026-10-22 01:25:06 +07:00
BFlat fe71ee2d75 Merge pull request #3399 from nrq6993-a11y/stream/vc-featD-manual-tate-chu-yoko
Character panel Tate-chu-yoko marks vertical type as a horizontal block
2026-10-22 01:24:50 +07:00
bflatastic 74ec2751ed Docs: Photoshop filter count after Fresco and Torn Edges (54/57), one row each 2026-10-22 01:15:10 +07:00
bflatastic eb9e064254 G2: Effect › Artistic › Fresco raster filter
Squashed from #3096 onto main.
2026-10-22 01:15:09 +07:00
bflatastic 5925e6339a G2: Effect › Sketch › Torn Edges raster filter
Squashed from #3010 onto main.
2026-10-22 01:06:25 +07:00
bflatastic b45bb3dd54 Character panel Tate-chu-yoko marks vertical type as a horizontal block
Squashed from #3399 onto main.
2026-10-22 01:06:24 +07:00
BFlat 875f98d211 Merge pull request #3453 from lehni/update/canvas-upload
Canvas: each update copies the rendered frame whole instead of pixel by pixel
2026-10-22 01:06:01 +07:00
BFlat c21ac5ca02 Merge pull request #3452 from nrq6993-a11y/stream/vc-feat-3343-pmd-unsupported
3343: recognize PageMaker .pmd on open with a clear message
2026-10-22 01:05:39 +07:00
BFlat 3987fdfca7 Merge pull request #3063 from nrq6993-a11y/stream/vc-feat1-g2-pathfinder-soft-mix
G2: Effect › Pathfinder › Soft Mix blends overlapping CMYK fills
2026-10-22 01:05:23 +07:00
BFlat 9439087946 Merge pull request #3412 from nrq6993-a11y/stream/vc-featD-g4-system-layout
G4: System Layout spaces every text object in whole points
2026-10-22 01:05:06 +07:00