Commit Graph
3400 Commits
Author SHA1 Message Date
Julius van der Vaart 24e3a15504 Merge branch 'main' of https://github.com/storytold/vectorcraft into 5421-line-arrowhead
# Conflicts:
#	docs/target-app-parity.md
2026-11-09 23:42:42 +01:00
dotCooCoo 93f75def04 Merge main into feat/command-param-schemas 2026-11-09 14:38:20 -08:00
BFlat 8591637999 Merge pull request #6359 from ruchirguitar/g2-effect-gallery-preview
G2: Effect Gallery thumbnails and an in-dialog preview
2026-11-10 05:33:33 +07:00
BFlat 39c1f0283f Merge pull request #6360 from dotCooCoo/fix/touchpad-ctrl-zoom
Canvas: Cmd/Ctrl-wheel input finer than a whole notch zooms; only whole notches scroll sideways
2026-11-10 05:28:23 +07:00
dotCooCoo 59304f9964 Fix #6316: a Transform effect's copies of a group are whole groups below the original
A Transform effect with copies on a group copied each member on its own,
so one member's copies lay over the fills of the next member. Each copy
is now a whole group, the original on top and each copy below the one
before. A path's copies follow the same order. Guides are not copied,
and the copies stop at the node limit. A group with its own fill or
stroke, a clipping group and live type keep their previous copies.
2026-11-09 14:27:25 -08:00
dotCooCoo 2e6ba25598 Commands: parameter schemas cover every route, bound hostile values and translate their errors
Check a new call's params against the schema in execute_spec, after the
key check and before the parser, and check every command.batch step
before the first one runs. menucmds::run_raw and the two other direct
runs go through the same check. Saved steps keep keys the schema does
not name and have the values it names checked.

Limit nesting to 16 levels, cut error text and paths to a fixed length,
and copy nothing before it has passed. Treat a whole number written
with a fraction as an integer. Check declared defaults and duplicate
names once at first use.

Give the five schema errors rows in the 22 complete-message catalogs.
2026-11-09 14:19:22 -08:00
Drew Dibble 59cc303912 Canvas redraw: the stack overflow fix's evidence, and two tests' known differences
- The parity rows say what the fix covers: a 3D effect on a fill or
  stroke that builds nothing overflowed the stack with no effect of the
  object's own too, on the canvas, in Object › Rasterize and in raster
  exports.
- The builds-nothing test says the fill-only difference (a raster
  effect clipped to the path, cutting Roughen's spikes, when drawn
  without the 3D effect) is an older bug, not the design.
- The traced-shape test says why its area is bounded rather than drawn
  again: a partial render in outline view differs from the whole by one
  in alpha on 37 pixels, older than the test and unrelated to the edit.
- A doc comment rewrapped.
2026-11-09 15:13:42 -07:00
dotCooCoo 5eb6b62632 Flatten: blend modes do not read the white under the art
Flatten Transparency composited each region over white, so a blend mode
on the bare page read that white. Raster renders now draw their
background under the finished art, and the flattened color no longer
matched them: a Color Burn object on the bare page flattened to white
and rendered in its own color. The region now composites the art alone
and puts the white under it.

- Tests that relied on the white under the art now draw art under the
  style (`every_builtin_style_paints_visibly_on_a_rectangle`) or compare
  only whole-pixel pans with a fresh render
  (`a_coarser_glow_kept_whole_draws_after_a_pan_as_made_again`).
- New tests cover every blend mode on white and blue backgrounds, a
  thumbnail and the ink planes with a Screen glow, and
  `over_background` at background and pixel alpha 0, 128 and 255.
2026-11-09 14:13:08 -08:00
dotCooCoo 39d538dadf Canvas: Cmd/Ctrl-wheel input finer than a whole notch zooms
With Scroll Sideways with Cmd/Ctrl + Wheel on, wheel() turned all
Cmd/Ctrl wheel motion into a sideways scroll unless it arrived as a
pinch event. A wheel turn now zooms about the pointer once it holds an
event from a trackpad source, point deltas from an unnamed source in the
desktop app, or line deltas that are not whole notches. Whole notches
keep scrolling sideways, and the option's default is unchanged. The same
rule applies with Zoom with Mouse Wheel on. egui-winit reports a wheel
source only on macOS, so the delta decides elsewhere.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-09 13:48:07 -08:00
ruchirguitarandCursor e1b73f38bc G2: Effect Gallery thumbnails and an in-dialog preview
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-10 03:12:54 +05:30
dotCooCoo 1796c77765 Merge main into feat/command-param-schemas 2026-11-09 13:31:22 -08:00
dotCooCoo 10909656d9 Path ops: Unite sweeps a single path once when its own sweep leaves its segments as they are
`unite_all` and `try_unite_all` swept each input under its own fill rule
and then swept all the resulting contours again under NonZero. With one
input whose sweep split and dropped none of its segments, the second
sweep ran over the same simple contours and doubled the time. Such an
input is now refit from the first sweep's contours. Inputs that cross
themselves and unions of several inputs are still swept again, and the
input paths are converted once instead of twice.
2026-11-09 13:20:20 -08:00
Drew Dibble bd9f6a04ef Canvas redraw: review follow-ups to the strengthened tests
- A 3D effect that builds nothing: af754bcb2 said the object draws exactly
  as without it under a Drop Shadow or Gaussian Blur. That holds only for
  a stroked object. With only a fill, the raster effect draws from the
  art made for the object, where without the 3D effect it is clipped to
  the path, so Roughen's spikes differ: the earlier wording was right.
  The test keeps the stroked cases exact and restores fill-only cases
  with a Drop Shadow and a Gaussian Blur, which differ in under 4% of
  the pixels and nowhere inside the path. Its reach check compares with
  the object drawn without its raster effect, since Roughen alone
  reaches past the path.
- The Vector Halftone test's bounds are a consistency check, and only
  holding no art tests the branch: its doc no longer says no solid is
  built (the free measure's halftone arm builds one). The overprint
  test's area check is labeled likewise.
- Recoloring a traced shape bounds the area the renderer that drew the
  trace object measures too, inflated by half the stroke and a pixel.
- The let-go test pins the nothing-to-draw branch: no frame, whole or
  part, began since the measure.
- The parity doc's feature row names the stack overflow fix and its
  test; a group test's doc says what its fixture holds.
2026-11-09 14:18:05 -07:00
dotCooCoo faea85f772 Fix #6125: raster exports keep a Screen glow on the bare page
A raster export filled its background into the page before the art, so
blend modes read it as art underneath: an Outer Glow in Screen mode, the
default, turned white on a white background and was missing from PNG and
JPEG files while the canvas showed it. Blending against nothing also
differed from the canvas for Difference and the other modes.

The background now goes under the finished art, in frames and in object
thumbnails. A blend mode reads only the art below it. A white object
under a Difference object still inverts.

Page Isolated Blending no longer changes a raster export on a bare page.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-09 13:02:28 -08:00
Ahmed Gomaa 323b3385bc Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 22:42:50 +02:00
dotCooCoo f688129ef2 Merge main into feat/command-param-schemas 2026-11-09 12:34:02 -08:00
Christian Lappin ef25dffe01 fix(mcp): validate and cancel Rotate View gestures (#6322) 2026-11-09 15:31:35 -05:00
Drew Dibble 2fcaaedb2d Merge main into type-3d-redraw 2026-11-09 13:20:30 -07:00
BFlat 9394a43e58 Merge pull request #6347 from jmverges/fix/6314-pdf-separation-images
PDF import: Separation images keep their ink (#6314)
2026-11-10 03:18:58 +07:00
Ahmed Gomaa 09d5322283 Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 21:59:07 +02:00
Julius van der Vaart 7d73882d3a Stroke: Line Arrow arrowhead (#5421)
Add Line Arrow, a 41st generated arrowhead: two arms as thick as the line
(at 100 % scale) meeting at right angles in a sharp tip, cut square at their
ends. It is saved by the new name `LineArrow`, appended so existing names
stay stable, and listed third in the arrowhead menus after Arrow (open).

Its arms spread four weights either side of the line, twice as wide as the
other heads, so Arrowhead now states its own reach and half width. Visual
bounds and clicks on the canvas (head_reach, head_contains) use them instead
of one fixed 4.6 x 2 box; every other head keeps the sizes it had.

Tests: the outline test checks each head against its own reach and half
width; a new test checks the line arrow's tip, corners, open middle and arm
thickness; outset_covers_arrowheads checks that the wider head grows the
outset; the saved-name list includes LineArrow.
2026-11-09 20:47:31 +01:00
Christian Lappin 1c8503f3e2 fix(mcp): route Rotate View gestures to the canvas (#6322) 2026-11-09 13:50:36 -05:00
HassanKhan f8ca2c09cb Merge remote-tracking branch 'upstream/main' into feat-4936-auto-spell-check
# Conflicts:
#	docs/gaps.md
#	docs/roadmap.md
#	docs/target-app-parity.md
#	docs/type-parity.md
2026-11-09 23:50:29 +05:00
Ahmed Gomaa 9fda083329 Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 20:49:32 +02:00
HassanKhan ff1079b3ce Auto Spell Check: underline the unknown words of the type on the canvas (part of #4936) 2026-11-09 23:41:41 +05:00
jmvergesandClaude Opus 5.5 ca59598cd7 PDF import: Separation images keep their ink (#6314)
An image in a Separation color space opened as an RGB image: its spot ink
was lost (no plate in Separations Preview), and Fill and Recolor Artwork
didn't reach its color.

It now opens as a grayscale image of its tints (white where it lays no
ink, black at 100 %, its Decode array applied; 1 to 16 bits a sample, or
one gray channel from its JPEG, CCITT, JBIG2 or JPEG 2000 decoder),
colorized by its ink at 100 %: the spot swatch, a process plate's CMYK
color, or Registration. Its mask becomes its opacity mask, as a CMYK
image's does. The ink is found by the image's color space among those the
file defines, once per image. The ink None, an ink whose color can't be
told, images inside an alpha soft mask, inline images and DeviceN images
open as before; samples that can't be read open in RGB with a warning, and
the ink gets no swatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 18:39:46 +00:00
Ahmed Gomaa 95a2527585 Merge remote-tracking branch 'upstream/main' into fix/pdf-export-mark-text 2026-11-09 19:47:08 +02:00
Ahmed Gomaa ad4b4f881e Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 19:46:57 +02:00
Ahmed Gomaa 9ffea06f82 Merge remote-tracking branch 'upstream/main' into fix/pdf-export-mark-text 2026-11-09 19:12:24 +02:00
Ahmed Gomaa f2c4743072 Merge remote-tracking branch 'upstream/main' into fix/pdf-import-actualtext 2026-11-09 19:12:14 +02:00
Drew Dibble baa5bab2ea Docs: the 3D-bounds map's sweeps and bound, and the change in the parity doc's revision history 2026-11-09 09:54:50 -07:00
Drew Dibble bd779077e5 Merge main into type-3d-redraw
# Conflicts:
#	crates/ui-egui/src/canvas/tests.rs
#	docs/target-app-parity.md
2026-11-09 09:49:25 -07:00
Fabio William Conceição bd9b1696e0 G5: built-in UI Frames symbol library with default 9-slice
Add Panel, Button and Bar HUD chrome as a second original symbol library so games can drop resizable UI frames without inventing art each time.
2026-11-09 16:29:22 +00:00
Ahmed Gomaa 9b797c06d1 PDF export: letters with marks are written once in the text layer
A mark glyph's vertical translation started a new draw_glyphs batch, so
krilla received the cluster's source range again and mapped its
characters twice. Copying or searching the exported PDF then found
doubled letters for Arabic harakat in any font, and for every dotted
letter in fonts that draw dots as zero-advance mark glyphs (Noto Sans,
Naskh and Kufi Arabic).

Keep compatible glyphs on the same layout line in one batch and carry
their relative vertical placement as per-glyph y_offset; horizontal
placement is unchanged (next_x - x advances). Font, size, linear
transform, line/column, paint run, list marker and hyphen boundaries
still split batches. Krilla keeps owning cluster mappings and
ActualText. No importer change.

Regressions decode the content stream and ToUnicode maps: one batch per
layout line, no duplicated cluster assignment, one ActualText per
multi-glyph cluster, contours within 0.05 pt of outline export; mixed
scripts, vertical columns, path rotations and PDF/X variants covered.
The reader round-trip stays an ignored test until the importer consumes
ActualText (#6165).

Addresses #6309.
2026-11-09 18:13:14 +02:00
makesomethingshit 9c4a17e345 #6307: Put spinner revision beside the numeric-field history 2026-11-10 00:59:32 +09:00
makesomethingshit e56f95270c #6307: Preserve concurrent parity revision entries 2026-11-10 00:58:06 +09:00
makesomethingshit 804e6d5b14 #6307: Keep parity evidence away from the changing header 2026-11-10 00:57:12 +09:00
makesomethingshit 898db5d72d #6307: Keep spinner evidence separate from shared status lines 2026-11-10 00:53:11 +09:00
makesomethingshit 5bf0f337df #6307: Keep numeric spinner arrows repeating while held 2026-11-10 00:45:55 +09:00
Ahmed Gomaa 6e71211a16 PDF import: preserve authored text in ActualText spans
Editable PDF import derived characters from glyph Unicode/CID mappings
even when the enclosing marked-content sequence supplied /ActualText.
A span that paints "xy" but says "AB", followed by "C", imported "xyC".

Track the outermost replacement owner per span (absent, explicitly
empty, consumed), decode it with the existing PDF text-string decoder,
emit it once at the first placeable glyph, and let the remaining glyphs
of the span advance the pen without phantom character slots or
inferred spaces. Authored stretches keep their logical order while
adjacent ordinary text still goes through visual-to-logical
reconstruction. Glyph identity still drives font matching. Depth and
size are bounded; oversized or unbalanced spans fall back to glyph
mappings with a warning.

Outlines mode and PDF export are unchanged. Parity docs updated,
scores unchanged.

Fixes #6165.
2026-11-09 17:43:28 +02:00
BFlat 7875114168 Merge pull request #6308 from Messhias/feat/g5-dynamic-symbol-part-appearance
G5: dynamic symbol parts take opacity, blend and non-solid paint
2026-11-09 22:31:51 +07:00
jmvergesandClaude Opus 5.5 def928c0dc PDF import: image masks open colorized by the color they are painted in (#6313)
A PDF image mask (`/ImageMask true`) painted in a solid color opened as an
RGB image with the color in its pixels: Fill and Recolor Artwork didn't
reach the color, a spot color lost its ink, and the same mask painted again
in another color took the first one, because the painted image was cached
by the mask alone, and so did an uncolored pattern whose cell draws a mask.

It now opens as a grayscale image of what it paints, colorized by that
color, as the .ai reader opens a 1-bit image mask (#5790). A spot color
keeps its swatch and tint. The page's walk counts paths, not images, so the
ink is found from the color space. Readings of a pattern cell are told
apart by colorized images' colors too. Inside an alpha soft mask, or
painted with a pattern, a mask opens as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 14:43:13 +00:00
Fabio William Conceição 84e7d55bc8 G5: finish Eyedropper and undo wording for a picked part
copyFrom only writes paints enabled for pickup and apply, and paint, Transparency and the Eyedropper record an undo step only when the override changes.
2026-11-09 14:42:18 +00:00
Fabio William Conceição a4ea6d6fbe Merge remote-tracking branch 'upstream/main' into feat/g5-dynamic-symbol-part-appearance
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-09 14:42:18 +00:00
Fabio William Conceição 0f2dde0282 G5: qualify when a picked part takes the Eyedropper and Transparency
copyFrom still edits the part when reverse, append and defaultsOnly are false, and reverse copies onto source. transparency.set records an undo step only when the override changes.
2026-11-09 14:27:19 +00:00
Fabio William Conceição e88e9077e7 G5: spell out part-paint targets and the pen gaps still open
A picked part takes transparency and the Eyedropper only when those calls omit their other targets. Art, Pattern and Bristle brushes, native Wayland and the web still do not take tilt, bearing or rotation.
2026-11-09 14:07:48 +00:00
Fabio William Conceição 08cc3d6ffa Merge remote-tracking branch 'upstream/main' into feat/g5-dynamic-symbol-part-appearance
# Conflicts:
#	docs/target-app-parity.md
2026-11-09 14:07:11 +00:00
Ahmed Gomaa 7020af6501 Merge remote-tracking branch 'upstream/main' into fix/macos-native-cursor-delivery 2026-11-09 15:59:17 +02:00
Patrick Nadeau 3befda6e12 M4: limit gradient documentation to PDF behavior 2026-11-09 08:45:23 -05:00
Patrick Nadeau ad7cf2898c M4: keep gradient evidence with October history 2026-11-09 08:45:23 -05:00