Commit Graph
100 Commits
Author SHA1 Message Date
bflatasticandClaude Opus 5.5 30ba774e6f Part of gap 2: Effect › Texture (Craquelure, Grain, Mosaic Tiles, Patchwork, Stained Glass, Texturizer)
Six raster effects on the pixel-filter pipeline
(vectorcraft_effects::pixel::texture), under a new Effect › Texture
submenu between Sharpen and Video in the Raster Effects section:

- Craquelure (crackSpacing pt 2..100, default 15; crackDepth 0..10, 6;
  crackBrightness 0..10, 9): the object on relief plaster that cracks into
  plates about Crack Spacing apart (a Voronoi network over jittered points)
  and along the quarter, half and three-quarter contours of its softened
  tones. Depth sets how dark and wide the cracks are and how high the
  plates' bevels and the tones stand (lit from the top left); Brightness
  how brightly the surface is lit.
- Grain (intensity 0..100, 40; contrast 0..100, 50 = unchanged; grainType
  Regular, Soft, Sprinkles, Clumped, Contrasty, Enlarged, Stippled,
  Horizontal, Vertical, Speckle; default Regular): coloured 1-point grains,
  smooth ones, clumps, 2-point grains, streaks along rows or columns, dark
  specks; Sprinkles and Stippled use the background colour, white.
- Mosaic Tiles (tileSize pt 2..100, 12; groutWidth 1..15, 3; lightenGrout
  0..10, 9): irregular tiles bevelled at their edges, with sunken grout half
  a point wide per step, lightened as Lighten Grout says.
- Patchwork (squareSize pt 0..10, 4; relief 0..25, 8): squares filled with
  the colour around their centres, raised to heights that follow the
  highlights and shadows, a little more or less at random.
- Stained Glass (cellSize pt 2..50, 10; borderThickness 1..20, 4;
  lightIntensity 0..10, 3): single-coloured panes leaded in the foreground
  colour (black, half a point per step), lit from behind at the object's
  centre and fading out towards its corners (PixelSpace gains `extent`).
- Texturizer (texture Brick, Burlap, Canvas, Sandstone, default Canvas;
  scaling % 50..200, 100; relief 0..50, 4; lightDirection Bottom, Bottom
  Left, Left, Top Left, Top, Top Right, Right, Bottom Right, default Top;
  invert): the object on a surface in relief. The four surfaces are height
  fields generated in code (bricks in stretcher bond, plain weaves coarse
  and fine, octaves of smooth noise); no image files. Load Texture is left
  out.

Every pattern lies in document space around the object's centre, so the
result is the same at any zoom or raster resolution, moves with the object
and is identical on every redraw (hash noise of cell indices); slopes are
taken in document units. Work per pixel is bounded (a 5 x 5 cell search,
four or five height samples, box blurs); parameters are clamped to their
ranges and finite-checked. The Pixelate helpers (Place, the cell search,
the softened colours) are shared, Mezzotint uses the shared smooth noise,
and the effect dialogs' dropdowns translate their labels in an "effect"
context where the plain word means something else (Soft, Horizontal and
Vertical are type settings in Japanese and Chinese).

Catalogue rows with parameter docs, outsets and reaches, menu entries,
dropdowns (Grain Type, Texture, Light Direction), translations, tests
(parameters and clamping, cracks and contours, ten distinct grains, tiles
and grout, squares in relief, leaded panes and the centre light, the
textures lit and inverted, the same at twice the resolution and when
moved, canvas, multithreaded, PDF and SVG, the command sweep with junk
parameters, the dialogs and the menu) and ROADMAP.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 19:31:47 +07:00
BFlat 32a688d68b Merge pull request #953 from crqch/fix-contributor-links
Fix contributor links
2026-10-10 18:50:11 +07:00
BFlat 5d07d646a9 Merge pull request #950 from seldoms/i18n/chinese-translations
i18n: wrap hardcoded UI strings for Chinese localization
2026-10-10 18:40:44 +07:00
bflatasticandClaude Opus 5.5 22443d8711 Keep CJK UI fallback fonts to ui_fonts
The app already finds an installed font for CJK (and other) characters
the UI fonts lack, the first time a frame paints one (ui_fonts): reading
a system CJK font at every startup duplicated that, cost a font file's
read and memory for interfaces that never show CJK, and broke its test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 18:36:15 +07:00
BFlat d428de6caa Merge pull request #952 from storytold/fix/949-artboard-label-width
Fix #949: artboard names fit their artboard when zoomed out
2026-10-10 18:25:02 +07:00
bflatasticandClaude Opus 5.5 6a13088840 Fix #949: artboard names fit their artboard when zoomed out
Artboard names are drawn at a fixed screen size above each artboard, so
zoomed out, where artboards shrink on screen, the names ran past them
and over their neighbours. A name is now no wider than its artboard on
screen, ending in an ellipsis when longer, and an artboard narrower
than 24 px shows none.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 18:24:50 +07:00
BFlat 18c9d27c8d Merge pull request #947 from IHAGI-c/fix/graph-blank-values
Graph Data: blank cells are left out, not drawn as zero; quoted numbers are labels
2026-10-10 18:16:26 +07:00
BFlat 3b32ea9626 Merge pull request #946 from rschuerer/fix/861-draw-non-native-art
Part of #861: draw non-native art in .ai editing data from its PDF
2026-10-10 18:13:52 +07:00
bflatasticandClaude Opus 5.5 42b198e3cb Graph data: constants after the imports
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:59:47 +07:00
bflatasticandClaude Opus 5.5 1446b4f5dc Keep the doc comment of unreadable on unreadable
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:58:55 +07:00
BFlat 7d6be31711 Merge pull request #948 from storytold/feat/brush-options-scatter-art-pattern
Part of gap 5: Scatter, Art and Pattern Brush Options
2026-10-10 17:57:25 +07:00
bflatasticandClaude Opus 5.5 2bc6c66c94 Part of gap 5: Scatter, Art and Pattern Brush Options
Double-clicking a Scatter, Art or Pattern brush in the Brushes panel (or the
panel menu's Brush Options...) now opens its options dialog, as Calligraphic
and Bristle brushes already did. OK runs brush.options and every stroke
painted with the brush redraws.

- Scatter Brush Options: Name; Size (10-1000 %), Spacing (10-10000 %),
  Scatter (-1000-1000 %) and Rotation (-180-180 deg), each Fixed (the first
  value), Random (between the two values) or Pressure (the first value at
  the lightest pen pressure, the second at the heaviest); Rotation relative
  to Page or Path. Scatter brushes now keep these modes (`modes`); brushes
  saved before keep their look (Random where the two values differ).
- Art Brush Options: Name; Width (1-1000 %); Scale Proportionately, Stretch
  to Fit Stroke Length or Stretch Between Guides with the guides' Start and
  End (% of the art length); the four Directions; Flip Along and Across.
- Pattern Brush Options: Name; Scale (1-10000 %), Spacing (0-10000 %); the
  five tiles (Outer Corner, Side, Inner Corner, Start, End) drawn with their
  art or None; Flip Along and Across; Stretch to fit, Add space to fit or
  Approximate path.
- All three: Colorization (None, Tints, Tints and Shades, Hue Shift with its
  Key Color picked from the art's colours, the most used one by default) and
  a live preview of a stroke painted with the edited brush.

Brush definitions from files and commands are now kept within these ranges
(Brush::sanitize, also for Calligraphic and Bristle values); unknown modes,
directions, fits or colorization methods are refused. The brush.options and
ui.brushOptions docs list the new params and fields. Tests: the brush model
(modes, pressure, sanitizing, art colours), engine params reaching the
brush and strokes redrawing, junk params in command_sweep, and headless
dialog tests for each dialog.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:48:05 +07:00
BFlat 5b198f3c00 Merge pull request #941 from IHAGI-c/fix/graph-line-options
Graph Type: Edge-to-Edge Lines for line graphs; radar follows Mark and Connect Data Points
2026-10-10 17:32:01 +07:00
bflatasticandClaude Opus 5.5 471c47f96a Graph Type: Edge-to-Edge Lines start off, as the reference app's do
New line graphs put their points at the centres of their categories, the
option's default in the reference app; graphs saved before the option
existed were drawn edge to edge and keep it (a field default of its own).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:31:33 +07:00
BFlat 7241726e56 Merge pull request #940 from IHAGI-c/fix/graph-axis-override
Graph Type: Override Calculated Values uses the exact value-axis range
2026-10-10 17:23:59 +07:00
BFlat 3bdaa45607 Merge pull request #945 from storytold/docs/readme-status-1010
Docs: README status for 2026-10-10
2026-10-10 17:22:12 +07:00
bflatasticandClaude Opus 5.5 b4c89f7301 Docs: README status for 2026-10-10 (PSD and PSB open and place)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:21:50 +07:00
BFlat 20c1a1621e Merge pull request #944 from storytold/fix/938-corner-widgets-multi
Fix #938: Live Corner widgets on every selected path
2026-10-10 17:20:05 +07:00
bflatasticandClaude Opus 5.5 d57134a308 Fix #938: Live Corner widgets on every selected path
The corner widgets only showed when the selection was exactly one path.
Now every selected path that has them shows its widgets: live rectangles
and polygons with the Selection tool, any path with Direct Selection,
each with its own corners (all of a path selected whole, the
Direct-Selected ones otherwise). Dragging any widget rounds every shown
corner of every path in one step, Alt-click cycles their kind, and the
red limit outline covers them all; a double-click opens Corners for the
path it was on. Each widget is drawn in its own layer's colour.

object.setLiveShape takes items: [{id, corners?}], several objects each
with its own corners, which the drag sends.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:19:52 +07:00
BFlat 9449c92136 Merge pull request #943 from storytold/feat/926-library-groups
Fix #926: the Libraries panel's search, groups and library export/import
2026-10-10 17:18:20 +07:00
bflatasticandClaude Opus 5.5 d62ecfe33a Fix #926: the Libraries panel's search, groups and library export/import
Search: a search field at the top of the Libraries panel filters the
current library's colours, character and paragraph styles and graphics
by name, ignoring case; groups without a match are hidden, groups with
one open, and a search nothing matches says so ("No results").

Groups: items can be put in user-named groups, kept in the library file
(`groups: [{name, items: [{kind, item}]}]`, left out when there are
none, so files written before groups load as they are). New commands:
library.createGroup {library?, name?, items?}, library.renameGroup
{library?, group, name}, library.deleteGroup {library?, group} (its
items stay, ungrouped) and library.moveItem {library?, kind, item,
group?}. An item is in one group at most; deleting an item takes it out
of its group. The panel shows each group as a collapsible section with
its item count after the ungrouped items (rename and delete on its
context menu), each item's context menu has Move to Group (No Group,
the groups, New Group...), and a New Group button sits in the footer.
library.get lists the groups, library.list counts them. The generic
command dialog takes fixed params in `__params` for this.

Export / import: library.export {library?, path?} writes a library
(colours, styles, graphics with art and thumbnails, groups) as a
.vclibrary file, the JSON the library folder keeps (without a path:
{data}); library.import {path | data | dataBase64, name?} adds one as a
new library, made current, numbered on a name clash ("Brand (2)").
The panel menu has Import Library... and Export Library..., through the
app's file dialogs (the web downloads, and picks through File > Open,
which now lists Libraries files). Imported and folder files are made
safe: at most 10,000 items of a kind and 1,000 groups, names clipped and
made unique, sizes finite, thumbnails kept only when their PNG header
says at most 1024 px a side, group entries naming missing items or
unknown kinds dropped; a file over 512 MB or that isn't a library is an
error. Paths go through the engine's file helpers (automation roots).
The importer is fuzzed (import_fuzz: garbage and mutated libraries).

Also fixed: the third graphic added to a library got the second's id
(`graphic-2` twice).

Docs: the commands' params docs, docs/mcp.md, ROADMAP.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:17:01 +07:00
BFlat c738400ebb Merge pull request #942 from storytold/feat/video-effects
Part of gap 2: Effect › Video (De-Interlace, NTSC Colors)
2026-10-10 17:06:09 +07:00
bflatasticandClaude Opus 5.5 c71af3079c Part of gap 2: Effect › Video (De-Interlace, NTSC Colors)
Adds the Video group to the raster effects, after Sharpen:

- De-Interlace…: Eliminate Odd or Even Fields, Create New Fields by
  Duplication or Interpolation. The fields are the rows of the document's
  raster grid (Document Raster Effects Settings › Resolution, carried to
  the filters as PixelSpace::line) counted from the top of the page, so
  the result is the same at any zoom and moves with the page. A line
  taken out copies the line above (the one below at the top), or takes
  the average of the two.
- NTSC Colors (no options, applied at once): colours a composite
  television signal can't carry, with luma plus chroma past 110 % of white
  or luma minus chroma below -20 % in YIQ, have their chroma cut to fit,
  keeping their luma. Saturated yellow, cyan and pure red lose some
  saturation; legal colours stay as they are.

Catalogue rows with parameter docs, dialog dropdowns, menu, translations,
tests (effects, canvas, command sweep junk, menu) and ROADMAP.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 17:05:56 +07:00
BFlat 7fb2c47006 Merge pull request #939 from storytold/fix/811-identify-unnamed-glyphs
Fix #811: unnamed glyphs of an installed font stay in their type
2026-10-10 16:46:54 +07:00
bflatasticandClaude Opus 5.5 a61aa93c1c Fix #811: unnamed glyphs of an installed font stay in their type
In a PDF (or the PDF part of an .ai file), a glyph of a subset font that
no ToUnicode map, CID table or character map of the font program names
was drawn as outlines, so one text object came in split: "RADA" as the
type "ADA" plus the R's outline.

Such a glyph is now looked for in the installed face of the font's name:
the first character (of those single-byte fonts encode: ASCII, Latin-1,
Latin Extended-A, punctuation, the euro and trade mark signs, fi and fl)
whose glyph draws the same outline, point for point within 2/1000 em,
names it. A subset carries the font's own outlines, so an installed copy
of the same font finds every glyph. Other versions of the font, empty
glyphs and glyphs that are no character still keep their outlines, with
the warning as before. Results are cached per glyph.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 16:46:39 +07:00
BFlat 552945f4e7 Merge pull request #936 from storytold/fix/927-direct-marquee-type
Part of #927: Direct Selection marquees take the type they touch
2026-10-10 16:19:59 +07:00
bflatasticandClaude Opus 5.5 7bf002af2b Part of #927: Direct Selection marquees take the type they touch
A Direct Selection (or Group Selection) marquee only gathered the
anchors of paths, so type, images, symbols and other objects without
anchors to pick were never selected by it. They are now selected whole
when the marquee touches them, as with the Selection tool, next to the
path anchors it holds; locked and hidden objects stay out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 16:19:44 +07:00
BFlat 3da4080b5e Merge pull request #935 from storytold/fix/918-place-psd
Fix #918: PSD and PSB files open and place as their merged image
2026-10-10 16:09:58 +07:00
bflatasticandClaude Opus 5.5 0eb4ce5e98 Fix #918: PSD and PSB files open and place as their merged image
File › Place and File › Open read PSD and PSB files: the merged image
every such document carries after its layers, which is what a linked PSD
shows. A placed PSD links like any image, so the Links panel updates and
relinks it, and it is sized by its ResolutionInfo resource.

The reader is written from the public file format specification. It
reads Bitmap, Grayscale, Duotone, Indexed, RGB, CMYK (through the colour
settings' CMYK) and Lab, at 1, 8, 16 and 32 bits per channel (32-bit
values are linear), raw, PackBits or zipped with or without prediction.
A document with transparency stores its merged image on white with the
alpha in the first extra channel. It comes back with straight colours,
also for 16- and 32-bit files, which say so in their Lr16/Lr32 block.
Multichannel files are refused with a message. The file is untrusted:
every read is bounds-checked and the image's size is checked against
the decode budget before anything is allocated.

PSB is a read-only format of its own, so exports never write a PSD under
a .psb name. The desktop packaging still doesn't associate either
extension with VectorCraft (UNASSOCIATED_EXTS): they belong to raster
editors. Layers (import options) are left for later.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 16:09:41 +07:00
BFlat be51213f0d Merge pull request #929 from haranishi/fix/eps-gradient-stop-cap
EPS import: bound the stitched-gradient builder
2026-10-10 16:06:43 +07:00
BFlat fe2d2ca173 Merge pull request #933 from storytold/fix/921-properties-gradient
Fix #921: the Properties panel's Gradient section with Type and Draw
2026-10-10 15:51:05 +07:00
bflatasticandClaude Opus 5.5 b3ed7df2a4 Fix #921: the Properties panel's Gradient section with Type and Draw
With the Gradient tool active, the Properties panel shows a Gradient
section: the type buttons (Linear, Radial, Freeform) and, for a
freeform gradient, Draw: Points or Lines as radio buttons. The Gradient
panel and the Properties panel share the type row and the draw mode
change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:50:23 +07:00
BFlat 93fb184939 Merge pull request #932 from storytold/fix/924-tab-leader-typing
Fix #924: the Tabs panel's Leader and Align On keep what is typed
2026-10-10 15:50:20 +07:00
bflatasticandClaude Opus 5.5 2ef32bb1a2 Fix #924: the Tabs panel's Leader and Align On keep what is typed
Both fields read their text from the tab stop again every frame, so each
keystroke was lost before Enter or a click away could apply it: the
field seemed to clear itself while typing. They now use the panels' text
field, which keeps the text being typed until it is committed. The
leader keeps spaces (". " for spaced dots), up to eight characters.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:49:49 +07:00
BFlat 5ccbbcca3f Merge pull request #931 from storytold/fix/925-links-on-focus
Fix #925: linked files changed in another app update when the window comes back
2026-10-10 15:49:46 +07:00
bflatasticandClaude Opus 5.5 11beb8fff1 Fix #925: linked files changed in another app update when the window comes back
Preferences › File Handling › Update Links only acted when a document
opened, so a linked image edited in another app while VectorCraft stayed
open kept its old pixels until Update Link in the Links panel, even with
Automatically chosen.

When the window comes back to the front, the active document's links
are now checked. With Automatically, changed files are read again; with
Ask When Modified, they are offered for update, once per change of a
file (keyed by path, size and modification time, since two saves can
share a time); with Manually, the Links panel shows them as modified.
Nothing is asked while a dialog is open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:49:08 +07:00
BFlat 04eb5e52c8 Merge pull request #930 from storytold/feat/pixelate-effects
Part of gap 2: Effect › Pixelate (Color Halftone, Crystallize, Mezzotint, Pointillize)
2026-10-10 15:47:10 +07:00
bflatasticandClaude Opus 5.5 9bad0a24ca Part of gap 2: Effect › Pixelate (Color Halftone, Crystallize, Mezzotint, Pointillize)
Four Photoshop-style raster effects on the pixel-filter pipeline
(vectorcraft_effects::pixel::pixelate), under a new Effect › Pixelate
submenu between Blur and Sharpen in the Raster Effects section:

- Color Halftone (maxRadius 4..127, default 8; channel1..channel4 screen
  angles -360..360, defaults 108/162/90/45): each colour channel is
  screened at its angle in square cells sized so a dot of Max. Radius
  fills one; each cell's dot covers the share of the cell that is the
  channel's coverage-weighted mean there (white stays white, black
  black). RGB documents screen R, G, B (channels 1 to 3); CMYK documents
  screen C, M, Y, K inks (channels 1 to 4), also when they are drawn ink
  plane by ink plane (the K plane uses channel 4).
- Crystallize (cellSize 3..300, default 10): every pixel takes the
  colour at the nearest of one jittered point per cell (exact Voronoi
  over a 5 x 5 neighbourhood, pruned by distance).
- Mezzotint (type: Fine/Medium/Grainy/Coarse Dots, Short/Medium/Long
  Lines, Short/Medium/Long Strokes; default Fine Dots; a dropdown in the
  dialog): each channel is turned fully on or off against its own random
  threshold pattern, so the object becomes pure colours.
- Pointillize (cellSize 3..300, default 5): one dot of random size per
  cell at a jittered point, coloured by the softened object there and as
  opaque as the object at its centre, stacked in random order over a
  white canvas where the object is.

Lengths are in points (Scale Strokes & Effects scales them) and every
pattern lies in document space around the object's centre, so the
result is the same at any zoom or raster resolution, moves with the
object, and is identical on every redraw (hash noise of the pattern's
cell indices, no state). Work per pixel is bounded whatever the
parameters, which are clamped to their ranges and finite-checked; the
halftone's cell grid is capped by the raster's size and a screen finer
than 3 pixels leaves the image as it is (its average). PixelSpace gains
`channels` so the renderer tells the filters what the channels hold.

Catalogue rows with parameter docs, outsets and reaches for cropping,
menu entries, dialog labels (Max. Radius, Channel 1-4, Cell Size), the
Mezzotint Type dropdown, translations, and tests: parameters and
clamping, tone and coverage, CMYK inks, polygon crystals, pure-colour
mezzotints with ten distinct patterns, dots on a white canvas, the same
result at twice the resolution and when moved, the canvas, PDF and SVG
through the engine, the command sweep with junk parameters, the dialogs
and the menu.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:42:24 +07:00
BFlat 2d6014583a Merge pull request #923 from callmeBalloch/fix/artboard-artwork-movement
Fix artwork movement when editing artboard X/Y coordinates
2026-10-10 15:29:47 +07:00
bflatasticandClaude Opus 5.5 f3f5e38bb6 ROADMAP: the #922 note joins the Last updated list
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:06:59 +07:00
BFlat e1599a16aa Merge pull request #799 from vbasky/feat/graph-series-palette
Colour graph series through Group Selection
2026-10-10 14:37:23 +07:00
bflatasticandClaude Opus 5.5 f21f8a89ce Graph series: find series art in one pass and ignore indices past the series
Painting looked up each selected object's graph by walking up through
parent_of, a search of the whole document per level, so a fill or stroke
change on a large selection grew with the square of the document. The
series art of every graph is now mapped in one pass, and documents with
no graph skip the lookup.

A series index comes from the file: one past the graph's series grew the
graph's series paints to that length. Such a group is no longer taken
for a series.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 14:33:41 +07:00
BFlat dd61dfa146 Merge pull request #920 from storytold/feat/885-transform-effect-dialog
Part of #885: the Transform effect's dialog takes Transform Each's controls
2026-10-10 14:32:55 +07:00
bflatasticandClaude Opus 5.5 20e5a746bd Part of #885: the Transform effect's dialog takes Transform Each's controls
Effect › Distort & Transform › Transform… was a plain list of fields.
It now has Transform Each's layout: Scale and Move with sliders, Rotate
with an angle dial, then Copies, Reflect X and Y, the reference point and
Random, kept with the effect so editing it from the Appearance panel
shows them again.

- The effect scales, rotates and reflects about the chosen point of the
  9-point grid (`reference`, the centre by default).
- Random takes a share of each value, drawn from the object's id: each
  object varies its own way and keeps its result on every redraw; a
  group's members move together.
- Copies stop before one reaches past 1e9 pt, and the scale and move are
  capped, so large values can't overflow.
- Transform Each and the effect share the sections and options code; the
  angle dial is a new widget.
- A plain number field now takes the focus when it is a dialog's first
  field, so both dialogs open with Scale › Horizontal ready for typing.

Transform Objects, Transform Patterns and Scale Strokes & Effects are not
in the effect yet: the geometry effects reshape paths only.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 14:32:10 +07:00
BFlat da73a46137 Merge pull request #919 from storytold/feat/832-automation-roots
Fix #832: --automation-read-root and --automation-write-root confine the MCP server's files
2026-10-10 14:28:11 +07:00
bflatasticandClaude Opus 5.5 9f875050ef Fix #832: --automation-read-root and --automation-write-root confine the MCP server's files
vectorcraft-cli mcp and vectorcraft --control take the flags PhotoCraft
takes. While roots are in force, every path a command reads (open, place,
relink, SVG image links, library and profile loads, plug-ins, preset
imports, font searches) must lie inside the read root and every path it
writes (save, export, package, Export for Screens and for Web, print to
file, captures, library saves) inside the write root. Paths are made
absolute, links are followed (a missing file's nearest folder's), and the
result is compared by whole components, ignoring case on Windows; `..`
below a missing folder, dangling links and device names are refused. A
root left out grants none of its access; without the flags nothing
changes.

The checks live in one place, vectorcraft_engine::file_access, consulted
by the engine's file helpers and the app's file services. The headless
server confines its whole process; the app confines control requests,
the frames carrying input they inject and the background saves they
start, leaving the person at the keyboard and the app's own folders
alone. The screenshot tool now has the backend write its file.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 14:27:24 +07:00
BFlat ab69087d68 Merge pull request #915 from Messhias/feat/394-display-print-size
Part of #394: Display Print Size at 100% Zoom drives Actual Size
2026-10-10 14:26:31 +07:00
bflatasticandClaude Opus 5.5 77e2a30c6d Part of #394: Actual Size shows print size whatever the display scaling
Display Print Size at 100% Zoom divided an assumed 96 pixels per inch by
the display's scale factor, so on a scaled display (150%, Retina) a
document inch came out a fraction of an inch. Nothing measures the
screen's real density, so an inch is now 96 screen points, the reference
density display scaling is set against, at any scale factor. The unused
screen_ppi and pixels_per_point fields go.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 14:25:50 +07:00
BFlat 90818cae40 Merge pull request #910 from Messhias/feat/394-font-names-in-english
Part of #394: Show Font Names in English labels the font menus
2026-10-10 14:25:15 +07:00
BFlat 3ab2af0744 Merge pull request #917 from storytold/fix/909-profile-preview-scale
Fix #909: a Width tool profile's preview fits the Profile menu
2026-10-10 13:53:54 +07:00
bflatasticandClaude Opus 5.5 8d2a3f48a1 Fix #909: a Width tool profile's preview fits the Profile menu
The Profile menu's preview drew a stroke's width profile assuming its
widths stay within the stroke weight. A profile made with the Width tool
can be many times wider, so its silhouette spilled over the Stroke panel.
It is now scaled to the preview by its widest point and clipped to it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 13:52:41 +07:00
BFlat 71003386ac Merge pull request #916 from storytold/fix/900-segmented-field
Fix #900: spinner fields read as one box in three parts
2026-10-10 13:32:13 +07:00
BFlat bd439727dd Merge pull request #914 from storytold/feat/812-tool-options
Part of #812: polygon properties, Flare Tool Options, more tool double-clicks
2026-10-10 13:23:32 +07:00
BFlat 809c4266a4 Merge pull request #913 from storytold/fix/901-shift-click-target
Fix #901: Shift-click a target circle in the Layers panel to add or remove it
2026-10-10 13:15:31 +07:00
BFlat 994e821f53 Merge pull request #912 from storytold/fix/903-reselect-after-deselect
Fix #903: Reselect repeats a Same command after Deselect
2026-10-10 13:15:17 +07:00
bflatasticandClaude Opus 5.5 2543da7cf0 Fix #900: spinner fields read as one box in three parts
A number field with a spinner and a preset list (stroke weight, font
size, leading…) was three boxes side by side: the field came out a
point taller than the spinner and the chevron, and each joint had two
borders. The field is now exactly as tall as the other controls of a
row, with its text centred, and the three parts share their borders.
num_field draws its box with the panel text fields' code instead of a
copy of it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 13:13:41 +07:00
bflatasticandClaude Opus 5.5 990d869897 Part of #812: more tools open their options on a double-click
Double-clicking a tool's button (or tool.options {tool}) now also opens:
- Artboard tool: Artboard Options of the active artboard (the Artboard
  tool's while it is in use, else the window's);
- the graph tools: Graph Type for the selected graph (an error without
  one), the dialog Object > Graph > Type opens;
- the Symbolism tools: Symbolism Tools Options with the brush the eight
  tools share (Diameter, Intensity, Symbol Set Density);
- Magic Wand: the Magic Wand panel.

The Object > Graph dialogs' opener is shared with the toolbar. The new
labels are translated in the eight complete catalogs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 13:00:21 +07:00
bflatasticandClaude Opus 5.5 ae27d899b8 Part of #812: Flare Tool Options last and open from the toolbar
The Flare tool keeps its options (Center: Diameter, Opacity, Brightness;
Halo: Growth, Fuzziness; Rays: on/off, Number, Longest, Fuzziness; Rings:
on/off, Path, Number, Largest, Direction) as persistent tool options,
saved with the preferences. The next flare dragged out uses them (the drag
still sets the centre and diameter, and Up/Down the ray count), a click
with the tool opens them filled in, and double-clicking the tool (or
tool.options {tool: "flare"}) opens them to edit: OK keeps them and draws
nothing. Before, the click dialog was the generic parameter form with
fixed defaults and the drag always used the command's defaults.

The new Flare Tool Options dialog lays the four groups out in two
columns; Rays and Rings have their checkboxes, and every value is kept
within its range. Its labels are translated in the eight complete
catalogs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 13:00:21 +07:00
bflatasticandClaude Opus 5.5 7c0ce8a382 Part of #812: polygon properties in the Properties and Transform panels
A selected live polygon now shows Illustrator's Polygon Properties in the
Transform panel and the Properties panel's Transform section: side count,
angle, corner type and radius, radius, side length and Make Sides Equal
(enabled once an uneven scale has made its sides differ). Before, only the
side count and corner radius were there.

object.setLiveShape takes polygonAngle (degrees counterclockwise),
polygonRadius and sideLength (points, centre to vertex / side) and
makeSidesEqual, which drops the uneven scale and shear and keeps the
polygon's centre, angle and mean radius. Each call is one undo step; a
radius or length that isn't a number above 0 is an error. A star stays a
plain path, as in Illustrator.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 13:00:21 +07:00
BFlat 5305b80308 Merge pull request #899 from vbasky/credit/vbasky-name
Credit vbasky by real and display name
2026-10-10 12:56:25 +07:00
bflatasticandClaude Opus 5.5 980cc4fe44 Fix #901: Shift-click a target circle in the Layers panel to add or remove it
Clicking an object's target circle in the Layers panel always replaced
the selection, so several objects couldn't be picked there. Shift-click
now adds the object (a layer: its art) to the selection, or takes it out
when it is selected already, as in Illustrator; nothing stays targeted
then. layer.target takes add: true for it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 12:55:38 +07:00
bflatasticandClaude Opus 5.5 6917984329 Fix #903: Reselect repeats a Same command after Deselect
Select › Reselect repeated the last selection command, but a Select Same
command needs a selected object to compare with, so after Deselect it
failed with "nothing selected". Reselect now remembers the objects that
were selected when the command ran and, with nothing selected, takes the
reference from those still in the document.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 12:55:37 +07:00
BFlat ba2fc64d89 Merge pull request #906 from storytold/feat/852-pressure-brushes
Part of #852: Brush Options for Calligraphic and Bristle brushes, pen pressure
2026-10-10 12:38:10 +07:00
bflatasticandClaude Opus 5.5 5cf9233d26 Part of #852: Brush Options for Calligraphic and Bristle brushes, pen pressure
Double-clicking a brush in the Brushes panel (or the panel menu's Brush
Options…) opens its options. Calligraphic Brush Options: Angle,
Roundness and Size, each Fixed, Random or Pressure with its Variation,
over live previews of the nib and of a stroke. Bristle Brush Options:
Shape and the bristle sliders. OK runs brush.options; strokes painted
with the brush update.

The Paintbrush records the pen pressure along a stroke (path.freehand
takes [x, y, pressure] points), and a Calligraphic brush with Pressure
variation changes its nib along the stroke, from the value less the
variation at the lightest pressure to the value plus it at the heaviest.
Brushes saved before keep their Random variation. Pen pressure doesn't
reach the app on macOS yet (winit 0.30 reports none there).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 12:15:18 +07:00
BFlat db23e80ec4 Merge pull request #897 from storytold/fix/886-shift-anchor-guides
Fix #886: Smart Guides keep working on a Shift-constrained anchor drag
2026-10-10 12:00:28 +07:00
BFlat da010c33a1 Merge pull request #896 from storytold/fix/888-smooth-wheel-zoom
Fix #888: wheel notches zoom in a glide with Zoom with Mouse Wheel
2026-10-10 12:00:22 +07:00
bflatasticandClaude Opus 5.5 e47d542680 Fix #886: Smart Guides keep working on a Shift-constrained anchor drag
Dragging anchors with Direct Selection snapped to points, paths and
Smart Guides, but with Shift held the move kept its 45° angle and
snapped to nothing. The grabbed anchor now slides along the constrained
line onto the anchors, paths and alignment lines that cross it, as the
drawing tools' Shift does (counted from General › Constrain Angle).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:49:56 +07:00
bflatasticandClaude Opus 5.5 d8759492df Fix #888: wheel notches zoom in a glide with Zoom with Mouse Wheel
With General › Zoom with Mouse Wheel, each wheel notch's zoom was
applied on the frame it arrived, so the view jumped a step per notch
while scrolling glides over a few frames. A mouse wheel's notches now
glide in (what is left shrinks by e every 50 ms), ending at the same
zoom; a trackpad's fine steps still apply at once.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:49:54 +07:00
BFlat 6ba5e0585e Merge pull request #895 from storytold/fix/867-macos-dialog-thread
Fix #867: macOS file dialogs no longer run inside the window's event handler
2026-10-10 11:49:20 +07:00
BFlat 4c1e16d791 Merge pull request #894 from storytold/fix/890-artboard-edge-art
Fix #890: artboard art includes art flush with its right or bottom edge
2026-10-10 11:49:13 +07:00
bflatasticandClaude Opus 5.5 dd8f144770 Fix #867: macOS file dialogs no longer run inside the window's event handler
On macOS the Open and Save panels ran modally on the UI thread, inside
the window's event handler. Resizing the panel delivered window events
to that handler again, and the app crashed when the mouse was released.
They now open from a thread of their own, as on Linux (#592): rfd runs
the panel on the main thread from the run loop, outside the handler, and
the app picks the answer up when it comes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:30:33 +07:00
bflatasticandClaude Opus 5.5 6c131431ed Fix #890: artboard art includes art flush with its right or bottom edge
The art that goes with an artboard (Duplicate Artboard and Copy/Cut with
art, the Artboard tool's Move/Copy Artwork with Artboard, and moving an
artboard by its X and Y) was found with a half-open containment test, so
an object whose right or bottom edge lay exactly on the artboard's was
left behind. Its edges now count as inside.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:30:32 +07:00
BFlat 8ae59bf6b7 Merge pull request #892 from storytold/fix/787-precise-export
Fix #787: raster exports keep translucent edges over opaque art opaque
2026-10-10 11:29:36 +07:00
BFlat b47f611e18 Merge pull request #891 from storytold/fix/798-curvature-any-path
Fix #798: the Curvature tool edits any selected path
2026-10-10 11:29:31 +07:00
BFlat 02d02f660f Merge pull request #889 from storytold/pr/roadmap-batch-2026-10-10
Docs: ROADMAP for the 2026-10-10 fixes; Other Library lists color books
2026-10-10 11:12:50 +07:00
bflatasticandClaude Opus 5.5 4099ebf3c9 Fix #787: raster exports keep translucent edges over opaque art opaque
The renderer composited in 8-bit integers, so where a partly transparent
anti-aliased edge crossed opaque art (or a background colour) the result
came out at alpha 254 on some pixels, and PNG, TIFF and WebP files were
written with an alpha channel. Raster exports (and Save for Web) now
composite in floating point (vello_cpu's f32 pipeline, enabled as a
feature), offscreen groups, masks and patterns included; the canvas keeps
the faster 8-bit path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:12:13 +07:00
bflatasticandClaude Opus 5.5 1db82cbc02 Fix #798: the Curvature tool edits any selected path
The Curvature tool only edited the path it was drawing. It now edits any
selected path, whatever drew it, keeping its shape except where edited:
a click on a point makes it the current (direct-selected) point and a
drag moves it, re-curving only its two segments (the neighbours keep
their handle directions); Alt-click or double-click toggles it smooth or
corner and Delete removes it; a click on a segment adds a smooth point
without changing the shape, and a drag moves it in the same undo step.
With an end of an open path current, clicks go on from it (the old
segments keep their shape) and a click on the other end closes it.

The edits go through a new path.curvatureEdit command (move, insert,
extend, close), path.convertAnchor and path.removeAnchor, one undo step
each. The tool now claims Delete/Backspace while it has a point to
remove, so the key no longer deletes the whole path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:12:10 +07:00
bflatasticandClaude Opus 5.5 898c4f7677 Docs: ROADMAP for the 2026-10-10 fixes; Other Library lists color books
The ROADMAP's last-updated line names this batch's fixes and the two
community PRs that didn't add themselves (#792, #765); the platforms
paragraph says Windows starts on Direct3D 12 and loads no Vulkan driver
unless asked (#806); the guides row has ruler guides with Smart Guides
on and the hover labels (#812). Window › Swatch Libraries › Other
Library's description lists .acb color books (#831).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 10:52:27 +07:00
BFlat 6b42a9100c Merge pull request #887 from storytold/fix/812-hover-labels
Part of #812: Smart Guides label an object's centre and anchors on hover
2026-10-10 10:46:53 +07:00
BFlat 1b398978ba Merge pull request #884 from storytold/fix/827-raster-effect-blend
Fix #827: shadows and glows keep their blend modes in PDF
2026-10-10 10:46:45 +07:00
BFlat 449387a62e Merge pull request #883 from storytold/fix/812-guides-snap
Part of #812: ruler guides pull drawn points with Smart Guides on
2026-10-10 10:46:28 +07:00
BFlat 0782972b88 Merge pull request #882 from storytold/fix/785-step-references
Part of #785: run and command_batch steps can use earlier results
2026-10-10 10:46:10 +07:00
BFlat 07708f6cca Merge pull request #881 from storytold/fix/861-open-error-dialog
Part of #861: a file the user can't open is reported in a dialog
2026-10-10 10:46:01 +07:00
BFlat 5b26fd4d01 Merge pull request #879 from storytold/fix/831-acb-color-books
Fix #831: color books (.acb) open as swatch libraries
2026-10-10 10:45:54 +07:00
BFlat a05a6d06bf Merge pull request #878 from storytold/fix/833-isolation-locks-outside
Fix #833: isolation mode locks and dims the art around the group
2026-10-10 10:45:48 +07:00
BFlat fd59778c8f Merge pull request #877 from storytold/fix/775-properties-paragraph
Fix #775: the Properties panel's Paragraph section justifies and hyphenates
2026-10-10 10:45:43 +07:00
BFlat 06d61296f5 Merge pull request #876 from storytold/fix/789-align-to-everywhere
Fix #789: every align button aligns to the Align To choice
2026-10-10 10:45:36 +07:00
BFlat fb4b84c4b9 Merge pull request #875 from storytold/fix/835-gradient-stop-recent
Fix #835: a recent colour recolours the selected gradient stop
2026-10-10 10:45:30 +07:00
BFlat 9c0eccb067 Merge pull request #874 from storytold/fix/862-stop-popover-beside-art
Fix #862: the gradient stop popover opens beside the art
2026-10-10 10:45:22 +07:00
BFlat 2b01ebcc9e Merge pull request #873 from storytold/fix/826-rotated-rulers
Fix #826: rulers cover their length in a rotated view
2026-10-10 10:45:15 +07:00
BFlat 447fe10edf Merge pull request #872 from storytold/fix/839-sfw-pixel-size
Fix #839: Save for Web accepts a typed width or height
2026-10-10 10:45:09 +07:00
BFlat 9cc0ca866d Merge pull request #871 from storytold/fix/824-artboard-label
Fix #824: the Artboard tool names its artboard once
2026-10-10 10:45:03 +07:00
BFlat 56b3119288 Merge pull request #870 from storytold/fix/806-no-vulkan-on-windows
Fix #806: Windows doesn't load Vulkan drivers unless asked
2026-10-10 10:44:58 +07:00
BFlat 0b249c5257 Merge pull request #869 from storytold/fix/758-skip-hopeless-prune
Part of #758: .ai import doesn't weigh text objects when the layers can't be used
2026-10-10 10:44:52 +07:00
BFlat c1bcd0afeb Merge pull request #863 from storytold/fix/755
Fix #755: blurred type no longer shifts as the view moves
2026-10-10 10:44:41 +07:00
BFlat 5d5db434ea Merge pull request #860 from storytold/fix/830-app-quit-pending
Fix #830: the control channel's app.quit says when it asks first
2026-10-10 10:44:34 +07:00
BFlat 84ae8e90c3 Merge pull request #859 from storytold/fix/828-effect-dropdowns
Fix #828: Offset Path's Joins and Zig Zag's Points are dropdowns
2026-10-10 10:44:27 +07:00
BFlat 71d8881186 Merge pull request #753 from storytold/feat/637-type-from-text-document
Part of #637: area type, threaded type and type on a path from the text document
2026-10-10 10:44:20 +07:00
bflatasticandClaude Opus 5.5 fdb7d7a183 Part of #812: Smart Guides label an object's centre and anchors on hover
With Smart Guides on, hovering the Selection tool near an object's centre
or one of its anchors now labels it ("center", "anchor"), as
Illustrator does, and a press there grabs the object by that point, so
the point follows the pointer and snaps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 10:28:38 +07:00
bflatasticandClaude Opus 5.5 99671cabd8 Fix #827: shadows and glows keep their blend modes in PDF
A raster effect painted below its object (Drop Shadow, Outer Glow) is
written as an image under the object's vector art. The image was
rendered over nothing and placed with Normal blending, so a Screen glow
or a Multiply shadow came out as Normal in the PDF. Each image is now
composited with its effects' blend mode, one image per mode when an
object's shadows and glows use several.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 10:28:04 +07:00