Commit Graph
4375 Commits
Author SHA1 Message Date
BFlat 511f36ed4c Merge pull request #7721 from dotCooCoo/fix/glyph-forms-review
Type: glyph forms and width forms follow the OpenType rules
2026-11-15 11:37:33 +07:00
BFlat dc8149cdf1 Merge pull request #7723 from dotCooCoo/fix/pdf-page-links-review
Import PDF: linked pages refuse placeholder .ai files, read the file once and keep blank pages
2026-11-15 11:37:26 +07:00
BFlat 3a2a8772f5 Merge pull request #7730 from dotCooCoo/fix/hpgl-9slice-art-bounds
Export: the HP-GL plot of the art's bounds places 9-slice and filtered symbol art before measuring
2026-11-15 11:37:09 +07:00
BFlat c7ed93dc31 Merge pull request #7736 from dotCooCoo/feat/pattern-move-tile-with-art
Pattern Options: Move Tile with Art moves the tile with the pattern's art
2026-11-15 11:36:50 +07:00
BFlat 94432bf2d0 Merge pull request #7729 from dotCooCoo/fix/pdf-image-profile-to-destination
PDF export: CMYK and other RGB destinations convert tagged images from their profile
2026-11-15 11:36:32 +07:00
BFlat 26878d3d0e Merge pull request #7715 from dotCooCoo/fix/svg-open-path-type-before-start
Type on a path: type on an open path can start before the path
2026-11-15 10:46:42 +07:00
BFlat 98b5d31f77 Merge pull request #7568 from dotCooCoo/fix/graph-design-art-aligned-rows
Graphs: aligned rows given with a design's art stay rows of its stack
2026-11-15 10:46:33 +07:00
BFlat d094a3c449 Merge pull request #7601 from ruchirguitar/feat/brush-tech-circuit
Brushes: built-in Tech Circuit brush library
2026-11-15 10:45:11 +07:00
dotCooCoo e9cd607aae Merge main into fix/glyph-forms-review 2026-11-14 19:20:09 -08:00
dotCooCoo f80c97ec14 Merge main into feat/pattern-move-tile-with-art 2026-11-14 19:00:56 -08:00
dotCooCoo 106133133b Merge main into fix/hpgl-9slice-art-bounds 2026-11-14 19:00:44 -08:00
dotCooCoo 0680b68b6d Merge main into fix/pdf-page-links-review 2026-11-14 18:51:27 -08:00
BFlat 7c12d660af Merge pull request #7627 from dotCooCoo/feat/ai-save-graph-records
.ai save: live graphs are written as graph records
2026-11-15 09:47:28 +07:00
BFlat 40f096f32b Merge pull request #7213 from dotCooCoo/feat/rotated-box-scale-reflect
Transform: Scale and Reflect act along a rotated bounding box
2026-11-15 09:47:18 +07:00
BFlat 3e68e4117a Merge pull request #7712 from dotCooCoo/feat/rough-pastels-load-texture
Effects: Rough Pastels loads its texture from an image file
2026-11-15 09:47:09 +07:00
BFlat 237fe27e50 Merge pull request #7713 from dotCooCoo/feat/psd-clipping-path
PSD: a file's clipping path clips its merged image on Open and Place
2026-11-15 09:46:45 +07:00
BFlat 563f075764 Merge pull request #7707 from dotCooCoo/feat/opentype-hv-style-roman-italics
OpenType panel: H or V Style and Roman Italics set kana and Latin forms
2026-11-15 09:46:29 +07:00
BFlat 55c2bb5194 Merge pull request #7511 from dotCooCoo/fix/live-paint-make-drawn-rows
Live Paint: Make keeps every fill and stroke row that draws on the source
2026-11-15 09:46:20 +07:00
dotCooCoo a20cf07fe3 Pattern Options: Move Tile with Art moves the tile with the pattern's art
Pattern Options gets the Move Tile with Art checkbox under Size Tile to
Art. With it on, a move of all of the tile art in pattern editing mode
moves the tile as far as the art moved, pixel-grid snapping included:
object.move, object.nudge, object.transform with a translation, and
drags with the Selection tool. A group counts as moved when each of its
members moved. A move of only
some of the art, a copy, a rotation, a scale and a move of
direct-selected anchors leave the tile where it is. The option is off
for a new pattern.

pattern.options takes moveTileWithArt and pattern.list reports it. A
pattern.options call that changes nothing no longer records an undo
step.
2026-11-14 18:19:17 -08:00
dotCooCoo 3b788515d1 Import PDF: linked pages on their trim boxes keep the bleed between artboards
Linked pages on their trim boxes were spaced by the 36 pt gap alone, so
with a large bleed one page's bleed box reached into the next artboard
and a page export could show part of its neighbor. The artboards are
now laid out once the document's bleed is known, 36 pt apart plus the
bleed on both sides: the document's bleed, or a page's own bleed box
where it reaches farther.
2026-11-14 17:56:30 -08:00
dotCooCoo 4ec16519a4 Export: the HP-GL plot of the art's bounds places 9-slice and filtered symbol art before measuring
The art's bounds no longer clip art that 9-slice guides place, or refuse
art that an instance shows through a nested instance:

- An instance whose art goes through 9-slice guides, at any depth, is
  measured as its art placed through the guides, with the objects the
  plot leaves out hidden after placing. Leaving them out first changed
  the box the guides cut.
- Hidden art is not placed, so it does not use up the limit on placed
  objects that the visible instances share.
- The copy of a dynamic symbol that an instance's changes are measured
  on keeps the symbol's 9-slice guides and natural size.
- The changes of the instances in a dynamic symbol's art are collected
  from all of the art, also from objects at 0% opacity or without paint,
  which an instance of the symbol can change.
2026-11-14 17:52:29 -08:00
ruchirguitar 1ab2743f8e G5: resolve Tech Circuit documentation merge conflict
Merge current main and retain both the Pencil snapping documentation and Tech Circuit library evidence. Only docs/mcp.md required manual conflict resolution. Focused checks passed: no conflict markers or whitespace errors, all 28 catalogs retain four unique nonempty labels, and brush implementation/tests remain unchanged. No full local Cargo CI rerun.
2026-11-15 07:21:46 +05:30
dotCooCoo 5956076b9f PDF export: CMYK and other RGB destinations convert tagged images from their profile
With Output › Convert to Destination and a CMYK destination, or an RGB
destination other than sRGB that images are converted to, an RGB image
that carries an ICC profile had its numbers read as sRGB, so a Display
P3 image came out with the wrong colors. Such an image is now converted
from its profile to sRGB with the color settings' rendering intent, then
to the destination.

- An untagged image converts from sRGB as before.
- A gray image keeps its profile, as gray is not converted.
- A profile the color engine can't read leaves the numbers read as sRGB,
  with a warning.
- Preserve Numbers is unchanged.

docs/mcp.md, the document.exportPdf params text and the progress doc
describe the behavior.
2026-11-14 17:44:50 -08:00
BFlat a53891b846 Merge pull request #7291 from dotCooCoo/feat/live-paint-bucket-multi-click
Live Paint: double-click floods across unstroked edges, triple-click paints the same paint
2026-11-15 08:25:35 +07:00
BFlat feaf72f2b1 Merge pull request #7692 from dotCooCoo/fix/graph-labels-embedded-newline-middle
Graphs: centered labels with a line break in their text stay centered
2026-11-15 08:25:19 +07:00
BFlat d593b41961 Merge pull request #7691 from dotCooCoo/feat/variable-library-every-kind
Variables: Load and Save Variable Library hold visibility, image and graph variables
2026-11-15 08:24:45 +07:00
BFlat 61091515b3 Merge pull request #7624 from dotCooCoo/fix/cmyk-tiff-alpha-and-extra-sample
TIFF: alpha after another extra sample places and opens as transparency
2026-11-15 08:24:36 +07:00
BFlat 2331fd44fa Merge pull request #7680 from dotCooCoo/feat/radial-blur-center
Effects: Radial Blur turns about a Blur Center set in its dialog
2026-11-15 08:24:28 +07:00
BFlat c6a085f20e Merge pull request #7704 from dotCooCoo/fix/perspective-repeated-ids
Perspective: a repeated id attaches, moves or transforms an object once
2026-11-15 08:23:55 +07:00
BFlat 40d1fc913a Merge pull request #7702 from dotCooCoo/fix/reverse-compound-stroke-records
Paths: Reverse Path Direction turns a compound path's own stroke width profile and pen records
2026-11-15 08:23:22 +07:00
dotCooCoo 7d205368e8 PDF export: Convert to Destination converts tagged images to sRGB
With Output > Convert to Destination and an sRGB destination, a gray or
RGB image that carries an ICC profile (a Display P3 TIFF, a PNG or JPEG
with an embedded profile) is converted from that profile to sRGB with
the color settings' rendering intent and written without the profile.
Before, it kept its own numbers and profile.

- A 16-bit image that is not resampled or recompressed stays at 16 bits
  a sample from PDF 1.5 on.
- A JPEG kept as JPEG whose samples the conversion leaves unchanged (an
  sRGB profile) keeps its JPEG data; other JPEGs are encoded again.
- A black-and-white image whose converted levels are gray is compressed
  as grayscale.
- A profile the color engine can't read is kept, with a warning.
- Without conversion, and with Preserve Numbers, images keep their
  profile as before.

IccProfile::to_srgb_pixels converts a run of pixels in one pass.
Docs: docs/mcp.md, document.exportPdf params, target-app-parity.
2026-11-14 16:59:18 -08:00
dotCooCoo e6bfe40d30 Import PDF: linked .ai pages open on their trim boxes with the bleed
With linkPages and cropTo: crop, a PDF-compatible .ai opened on its crop
boxes, while opening it as art uses its trim boxes. It now uses the trim
boxes too. A page on its trim box shows its bleed box round the
artboard, and the pages' bleed (the widest on each side) becomes the
document's bleed, as the importer sets it.
2026-11-14 16:42:06 -08:00
dotCooCoo cc7d081198 Import PDF: linked pages read the file once and keep blank pages
linkPages read and checked the whole PDF again for every page it
linked. The pages are now read from the file opened once. With
cropTo: bounding, a blank page stopped the open with "has no art to
place"; it now gets its crop box, as opening the page as art does.
2026-11-14 16:42:05 -08:00
dotCooCoo c730a1c776 Import PDF: linked pages refuse a .ai saved without PDF compatibility
linkPages refused other files but let a .ai whose page is only a
placeholder through, and each such page then showed the file's editing
data. A page read from editing data is now refused with the existing
error. The file is also hashed once for all its linked pages instead
of once per page.
2026-11-14 16:42:05 -08:00
dotCooCoo 8eded96792 PSD: transform a file's clipping path in place instead of copying it
file_clipped owns the path psdread::clipping_path reads, so it moves it
to the image's place without making a second copy of every anchor.
2026-11-14 16:39:17 -08:00
dotCooCoo 0f8b20c489 Type: glyph forms and width forms follow the OpenType rules
- A form other than the default, set with text.setRangeStyle or
  text.setFormat, takes away the characters' glyph choice, which would
  otherwise keep drawing its own glyph. "default" keeps it.
- With a width form (fwid, hwid, twid, qwid), shaping leaves out palt and
  turns kern and apkn off, and SVG output writes font-kerning: none and no
  palt, as the OpenType feature list asks. proportionalMetrics and kerning
  keep their values.
- The Glyphs panel menu counts a width form as available when a face has
  the feature in GSUB or GPOS.
- At a caret, the menu's check marks and its no-op check read all the
  text of the object, which is what the command formats. Choosing the
  current form again is not skipped when a character has a glyph choice.
2026-11-14 16:39:01 -08:00
dotCooCoo 8cba5fae0c Merge main into fix/live-paint-make-drawn-rows 2026-11-14 16:37:54 -08:00
dotCooCoo 15a6171021 Tests: texture-file tests remove their folders when they fail
The Rough Pastels and Glass texture tests make their folders with
vectorcraft_testkit::TempDir, which removes them on every exit path.
2026-11-14 16:32:18 -08:00
dotCooCoo c7aa27ec12 Transform: saved Scale and Reflect steps without a basis keep the page's axes
An action or journal entry recorded before Scale and Reflect followed the
turned bounding box has no basis value. Replayed, such a step now acts along
the page's axes, as it did when it was recorded; steps recorded now carry
basis "box" and replay along the box. The built-in Reflect Horizontal action
names basis "box", so it keeps reflecting across the box's own axis.

The symbol test that reflects a turned instance names basis "page", which
is the reflection it was written for.
2026-11-14 16:30:56 -08:00
dotCooCoo 2d790aab20 Merge main into fix/graph-design-art-aligned-rows 2026-11-14 16:21:34 -08:00
dotCooCoo af010b6dec PSD: a file's clipping path clips its merged image on Open and Place
A PSD or PSB file can name one of its saved paths (image resources 2000
to 2997) as its clipping path in resource 2999. psdread::clipping_path
reads that path in the image's pixel space, under the even-odd rule the
file format specification gives, with a subpath around the whole image
first when the initial fill record says the fill starts with all
pixels.

File > Place of such a file, and File > Open of its merged image, put
the image in a clip group of that path with no paint. file.place answers
the image's id as `image`, as for a DCS file. Replacing an image alone
in a clip group with such a file keeps the image's scale and rotation.
links.update and links.relink leave the clip group as it is. Files that
name no clipping path come in as before.
2026-11-14 15:55:34 -08:00
dotCooCoo 67fd1cd127 Merge main into feat/live-paint-bucket-multi-click 2026-11-14 15:48:45 -08:00
dotCooCoo 403023f834 Effects: Rough Pastels loads its texture from an image file
The Rough Pastels dialog has a Load Texture… button, as Glass and
Texturizer have. The image's gray levels become the paper surface,
stored with the effect as `textureImage` and listed as Loaded Texture
in the Texture menu; Scaling, Relief, Light Direction and Invert act on
it as on the built-in surfaces. The dialog's Texture and Light
Direction controls are now menus instead of text fields.

effect.apply and effect.setParams read `textureImage` from a file or
take the stored string and refuse anything else, and a plug-in filter
cannot have the host read a file for it.

In the Effect Gallery's Settings, a file dialog that answers later
(the macOS sheet, the Linux dialog) now gives the texture to the values
that asked: the filter being browsed, or the stack row that asked,
found by a number each row now carries. An answer for a removed row, a
filter no longer browsed or a gallery that closed is dropped.

Params text, docs/mcp.md, docs/control-protocol.md, docs/gaps.md and
the evidence line are updated.
2026-11-14 15:45:59 -08:00
dotCooCoo 094971e3ac Type on a path: type on an open path can start before the path
Type on an open path can now start before the path's start: its start
is stored below 0, the span runs from there, and the characters whose
middle falls before the path's start are not drawn, as SVG 2 lays out
text on a path (https://www.w3.org/TR/SVG2/text.html#TextLayoutPath).
The text keeps every character, and the start bracket stays at the
path's start. Past the path's end, text that does not fit is overflow,
as for other type on a path. Type that starts on the path draws every
glyph as before.

- SVG import keeps a <textPath> start before an open path's start
  (text-anchor end or middle, or a negative startOffset) instead of
  starting the text at the path's start, which drew every character.
- SVG export writes it as a negative startOffset.
- PDF export writes only the characters drawn on the path.
- The legacy .ai and .ai editing data writers write the type from the
  path's start with the type attributes warning.
- type.pathOptions takes a start below 0 for type on an open path; on a
  closed path it is the path's start, as before. A flip starts the type
  at its start bracket. Dragging the center bracket slides it from where
  it starts, and no further before the path.
- A click at the path's start places the caret by the first drawn
  character, and the caret in the hidden characters stands at the
  path's start. The highlight of substituted fonts and glyphs leaves
  them out.
- Release Type on a Path keeps the first drawn glyph where it was
  drawn, with the hidden characters before it.
- The Touch Type tool shows no box for a hidden character, and
  text.touchType returns an error for one. A character with a drawn
  glyph is changed by that glyph.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-14 15:44:12 -08:00
dotCooCoo d91e6a8565 Merge main into feat/opentype-hv-style-roman-italics 2026-11-14 15:24:42 -08:00
dotCooCoo 0431809643 OpenType panel: H or V Style and Roman Italics set kana and Latin forms
With Show East Asian Options on, the OpenType panel menu has H or V
Style and Roman Italics. H or V Style is the character feature tag
`hkna`: kana take the forms the font draws for horizontal type, and in
vertical type the shaper applies `vkna` in its place. Roman Italics is
`ital`, the font's italic half-width alphanumerics. Both are on or off
only (`hkna=2` is refused), set through `features` and
`featureChanges`, cleared by Reset OpenType Features, and are switches
in Character Style Options > OpenType Features.

Docs: docs/mcp.md, docs/type-parity.md, docs/target-app-parity.md.
2026-11-14 15:22:36 -08:00
dotCooCoo dba42af495 Merge main into feat/ai-save-graph-records 2026-11-14 15:21:09 -08:00
dotCooCoo 7ad98ce9b8 Perspective: a repeated id attaches, moves or transforms an object once
perspective.attach, perspective.release, perspective.move and
perspective.transform took their `ids` as given, so an id listed twice
was processed twice. Attach warped an object that was already projected
a second time, and a move or transform of an object not yet in
perspective attached it and then moved it twice. The Shift and Snap to
Grid reads of a move also used a document attached twice. The ids are
now taken once each, in the order first given.
2026-11-14 15:20:27 -08:00
BFlat dafd993395 Merge pull request #7658 from dotCooCoo/feat/svg-filter-defaults
Effects: Effect › SVG Filters lists default filters
2026-11-15 06:18:12 +07:00
BFlat 4e42e2bbb0 Merge pull request #7681 from dotCooCoo/feat/east-asian-glyph-forms
Type: Glyphs panel menu draws the selected characters in an East Asian glyph form
2026-11-15 06:17:55 +07:00