Commit Graph
8190 Commits
Author SHA1 Message Date
BFlat f239944df0 Merge pull request #7107 from dotCooCoo/fix/measured-arclen-coincident-quad
Paths: a quadratic segment whose points coincide measures zero length instead of NaN
2026-11-13 23:02:03 +07:00
BFlat b17a62be34 Merge pull request #7109 from dotCooCoo/fix/painted-fx-brush-reach
Effects: culling a painted piece leaves room for its own brush art
2026-11-13 23:01:55 +07:00
BFlat c8bf38c6a1 Merge pull request #7092 from dotCooCoo/fix/dimension-guide-line-snap
Dimension tool: a point on a Smart Guide stays on the guide
2026-11-13 23:01:45 +07:00
BFlat 017db27090 Merge pull request #7131 from dotCooCoo/fix/flatten-grouping-sweep-meets
Flatten: grouping sweeps skip boxes that a box already holds or cannot join
2026-11-13 23:01:18 +07:00
BFlat dc5c3aa444 Merge pull request #7119 from dotCooCoo/perf/pathops-overlap-sweep
Path ops: Offset Path sweeps long, low paths along their length
2026-11-13 23:01:08 +07:00
BFlat 7372d7ee5e Merge pull request #7081 from dotCooCoo/fix/svg-rtl-text-anchor
SVG: right-to-left text with text-anchor start or end opens at its directional edge
2026-11-13 23:00:55 +07:00
BFlat 02445d5f02 Merge pull request #7130 from dotCooCoo/fix/eps-image-samples-once
EPS: an image drawn more than once writes its samples once
2026-11-13 23:00:45 +07:00
BFlat 0455c12162 Merge pull request #7127 from dotCooCoo/fix/thread-empty-last-paragraph-style
Type: a threaded frame's empty last paragraph keeps a format given to it
2026-11-13 23:00:36 +07:00
BFlat e9459df52b Merge pull request #7099 from jmverges/fix/7097-top-object-split-curve
Envelopes: a top object's side that is one split curve follows its parameter
2026-11-13 23:00:21 +07:00
BFlat 77970c6924 Merge pull request #7082 from dotCooCoo/fix/smooth-resets-anchor-selection
Smooth tool: smoothing a path deselects its direct-selected anchors
2026-11-13 22:26:18 +07:00
BFlat 45acda45fe Merge pull request #7084 from dotCooCoo/feat/message-rows-id-nl-da-bg
i18n: Dutch translates status and error messages
2026-11-13 22:26:08 +07:00
BFlat 5fcfb0ce6e Merge pull request #7086 from dotCooCoo/feat/library-charstyle-menu
Libraries: a character style's menu offers Apply, Add to Character Styles, Rename and Delete
2026-11-13 22:24:41 +07:00
BFlat 7fb0a5b51b Merge pull request #7088 from dotCooCoo/fix/panel-drags-primary-button
Panels: item drags start only with the primary button, as Layers does
2026-11-13 22:23:19 +07:00
jmvergesandClaude Opus 5.5 e11155c692 Envelopes: a top object's split goes by the longer of handles or bends
The previous commit took the spans from how far each piece bends away
from the split whenever both handles there were within ONE_CURVE of the
anchor. A curve that barely moves at the split but doesn't bend there
(a straight one, say) has short handles and no bend, so that gave 0/0
and the side fell back to the polygon shares. Now the spans come from
whichever pair is the longer: the handles, or the bends (which go with
the squares of the spans). The check of every piece against the
rebuilt curve is unchanged.

Test: a_split_curve_keeps_the_top_object_patch_where_it_barely_moves_and_runs_straight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 14:42:07 +00:00
dotCooCoo 4cf010c130 Flatten: grouping sweeps skip boxes that a box already holds or cannot join
The sweep filtered by transparency kept every open box in one tree, so
a box without transparency met every open box without transparency it
overlapped, though such pairs never join. Both sweeps closed an open
box early only when a later box held it, so in a nest of boxes that
share their left and top edges and get smaller to the right and
bottom, each box met every earlier box around it. One see-through
object inside 512 nested opaque objects took 130,817 meets in the
unfiltered sweep and 131,328 in the filtered one.

The filtered sweep now keeps open see-through boxes and open opaque
boxes in separate trees. An opaque box looks only in the see-through
tree; a see-through box looks in both.

In both sweeps, a box inside an open box it met, ending no further
right, is not opened when that box joins everything it overlaps (any
box without the filter, a see-through box with it). Whatever later
overlaps the inner box overlaps the outer one.

The nest above now takes 512 meets in each sweep, and a nest of 512
boxes alone takes 511 in the unfiltered sweep where it took 130,816.
The groups are unchanged.
2026-11-13 05:42:03 -08:00
dotCooCoo 19ab993479 EPS: an image drawn more than once writes its samples once
An image placed several times in an EPS file (the pieces of an envelope
or a Warp effect, copies of one image, a symbol's instances) wrote its
whole ASCII85 data at every placement: 200 copies for one envelope at
the default fidelity, enough for a large photo to pass the 256 MB page
limit and lose pieces.

The samples of such an image are now written once in the setup as
VCim<i>, and each placement reads them from there:
- Level 3: a ReusableStreamDecode stream, rewound with resetfile and
  read through a new FlateDecode filter at each placement.
- Level 2: an array of strings of at most 49,152 compressed bytes, fed
  to RunLengthDecode by a procedure.

An image placed once is written where it is drawn, byte for byte as
before. The page limit counts a repeated image's samples once, and a
colorized image is reused per ink.
2026-11-13 05:38:06 -08:00
dotCooCoo 130f914868 Type: a threaded frame's empty last paragraph keeps a format given to it
A paragraph format given to the empty paragraph after a frame's last
paragraph break was lost when the story flowed again: the paragraph is
shared with the next frame's first paragraph, and the next frame's old
style replaced it, in that frame and in the frames after it.

- The thread reflow also notes which frames' last paragraph changed
  style, and story_paras_restyled keeps that style against the next
  frame's unedited first paragraph, across unedited empty frames too.
  When the same edit formats the next frame's first paragraph, that
  format applies, as before.
- story_paras keeps its behavior for its other callers.
- Tests cover area type and type on a path on either side, a next frame
  holding text, three frames, undo and redo, a format that changes
  nothing, and numbered list counts.
2026-11-13 05:27:02 -08:00
jmvergesandClaude Opus 5.5 6ed3935e59 Envelopes: a top object's side split at a cusp still follows its curve
Split where the curve stops (a cusp), both handles at the split lie on
the anchor, so their lengths say nothing of how the curve's parameter
divides between the two pieces, and the side fell back to the polygon
shares. When both handles lie within ONE_CURVE of the anchor, the
spans now come from how far each piece bends away from it (the second
derivatives, in proportion to the squares of the spans). The existing
check of every piece against the rebuilt curve is unchanged.

Test: a_split_curve_keeps_the_top_object_patch_when_split_at_a_cusp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 12:43:47 +00:00
dotCooCoo d956d2165f SVG: an absolutely placed right-to-left chunk is anchored by the edges of its glyphs
A text chunk placed by an absolute x was measured from the pen of its
first character to the farthest glyph end. The first character of a
right-to-left chunk is drawn at its right, so a chunk of several such
characters was measured as that one character: anchored by middle or
end, or starting a line beside absolutely placed characters, it opened
off its position by the width of its other characters.

- A chunk's left and right edges are the smallest glyph start and the
  largest glyph end over all its characters, as SVG 2 anchors a chunk
  (https://www.w3.org/TR/SVG2/text.html#TextLayoutAlgorithm). The first
  character's pen is placed at its own distance from the left edge.
- The layout that measures the chunks has the direction the imported
  text gets: left to right unless the text's direction is rtl. Text
  starting with a digit and holding right-to-left letters was measured
  right to left.
- The chunks are measured in the first of the layouts that kern the
  characters onto their x, so anchored text is laid out once less.
2026-11-13 04:32:32 -08:00
dotCooCoo 88c02aa293 Effects: culling a painted piece leaves room for its own brush art
A live-effect plug-in that paints its pieces draws each piece's brushed
stroke along the piece's path at the piece's stroke width. Culling left
room for brush art from the object's own stroke width around the
pieces, so brush art of a moved or wider piece was cut off at the edge
of the view. Culling now leaves 16 x the piece's stroke width + 8 pt
past each brushed piece, and does so for a symbol instance whose art
holds such a path (measured once per symbol) and for a blend, envelope
or repeat that holds one. Object > Rasterize measures the brush art
drawn along each piece and leaves out the object's own brush art, which
is not drawn.

Groups and layers now leave room for their members' brush art. The
cull bounds of a group or layer united its members' bounds without the
room each brushed member leaves, so the painted bounds of a group, and
the area redrawn when it changes, left out brush art past its members'
strokes. That applied to plain brushed paths as well as painted pieces.
Each member is now measured as the renderer measures it when it draws
the group, in the members of a group with a fill, stroke or adjustment
of its own and in a group with crop marks or Vector Halftone too.
2026-11-13 04:31:38 -08:00
dotCooCoo 2bd02ecb2a Paths: a quadratic segment whose points coincide measures zero length instead of NaN
measured_arclen returned kurbo's arc length unchecked. For a quadratic
segment whose three points coincide, kurbo 0.13.1's QuadBez::arclen
multiplies 0 by infinity and returns NaN. measured_arclen now returns 0
when the measurement is not finite, the same value it gives a segment it
does not measure. Finite results are unchanged.
2026-11-13 04:29:09 -08:00
dotCooCoo 727a26d5a6 Path ops: Offset Path sweeps long, low paths along their length
Offset Path now turns the overlap sweep the way Outline Stroke and
Unite do. When the estimate for its fill, the ring stroked around it
and the outline of its open subpaths is under two thirds as large for
the parts turned a quarter turn, the faces are found on the turned
parts, the faces within the offset distance of the path are dropped by
testing their points turned back, and the result is turned back.

On an open path of 10,000 anchors in rows of 1,000, offsetting by 2 pt
takes 1.0 s of processor time instead of 1.8 s in a release build.
The offset of a long, low path has as many subpaths as the offset of
the same path stood on end, and the area where the two differ is no
larger than the refit precision times the outline's length.
2026-11-13 04:26:14 -08:00
jmvergesandClaude Opus 5.5 728fd9ef14 Envelopes: a top object's side that is one split curve follows its parameter
A top-object envelope gives each piece of a side a share of the content
in proportion to its control polygon's length. When anchors split a
curve without changing its shape, the pieces' polygons don't divide the
side where the curve's own parameter does, so the envelope bent its
contents differently although its outline was the same: Add Anchor
Points on a top object moved the art, and a top object whose .ai mesh
saves each side's curve split into thirds drew its type up to about
half a point off its drawn art, which follows the whole curve's
parameter.

Coons::from_top_object now checks whether a side's pieces, from corner
to corner, are all pieces of one cubic. The pieces' spans of that
curve's parameter come from the handle lengths either side of each
split, the curve from the outer ends and handles, and every piece must
lie within 0.02 pt of the curve's piece over its span (each control
point). Such a side runs along that curve, by its parameter. Any other
side keeps the polygon shares, including a side only partly made of one
curve and a smooth side drawn in many pieces that isn't one curve as a
whole. Corners found from the outline can still move when anchors are
added, as before. Gradient meshes made from a path are unchanged.

Existing top-object envelopes with such sides redraw.
a_split_curve_moves_the_top_object_share_to_its_new_anchor, which
pinned the earlier behaviour, becomes a_split_curve_keeps_the_top_object_patch.

Tests: a_split_curve_keeps_the_top_object_patch,
a_top_object_joins_a_split_curve_saved_with_rounded_coordinates,
a_top_object_keeps_smoothly_joined_curves_apart,
a_top_object_side_partly_of_one_curve_keeps_the_polygon_shares and
a_top_object_side_of_many_arcs_stays_on_them (vectorcraft-doc),
envelope_top_object_keeps_its_look_when_anchors_are_added
(vectorcraft-engine) and
a_top_object_whose_top_is_one_curve_split_in_thirds_opens_live
(vectorcraft-eps).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 11:18:40 +00:00
BFlat 1dbdbce91f Merge pull request #7080 from dotCooCoo/feat/trace-create-strokes
Image Trace: Create Strokes makes a wide shape's thin features strokes and keeps its body a fill
2026-11-13 17:03:37 +07:00
BFlat 54f0c1b99b Merge pull request #7003 from mockydevs/fix/graphic-styles-list-height-2992
Graphic Styles: the list fills a taller panel above its footer
2026-11-13 17:03:22 +07:00
dotCooCoo 2129d00868 Dimension tool: a point on a Smart Guide stays on the guide
A Linear pick that the Smart Guides left where the pointer already was,
for example straight below the first point on the vertical construction
guide through it, or exactly in line with an object's center, was taken
as not snapped. The pick then moved to the closest point of a segment
within 8 pixels while the guide still showed it on the guide. The same
happened to a point already on a grid crossing with Snap to Grid on, or
on a whole pixel with Snap to Pixel on.

The pick now keeps the snapped point whenever the snap shows guides or
grid or pixel snapping is on. With Snap to Grid or Snap to Pixel on, a
pick off an anchor is no longer moved from the grid or the whole pixel
onto a segment. A point that no
anchor, guide, grid or pixel snapping places still lands on the closest
point of a segment. An anchor within 8 pixels, a segment within the
Smart Guides snapping tolerance and a nearby guide crossing still take
the point as before.

Docs: docs/dimensions.md, docs/target-app-parity.md.
2026-11-13 01:48:09 -08:00
dotCooCoo 345cd021dc i18n: Dutch translates status and error messages
Dutch was not in COMPLETE_MESSAGES, so with the interface in Dutch
script errors, plug-in manifest and permission errors, parameter
schema errors, 3D effect refusals, file-reader errors and data-set
messages showed in English.

- nl.tsv gains 557 `@msg` rows and one `@msgplural` row: the messages
  the German catalog translates and Dutch lacked. Most are one block
  with a header comment on their conventions, in the order de.tsv
  holds them; the rest sit next to the related existing rows.
  Backticked names, command ids, double-quoted values and bare true,
  false and null stay as the English writes them.
- nl joins COMPLETE_MESSAGES, so the message tests that iterate the
  list check Dutch too, and the untranslated report lists Dutch's
  missing messages. It lists the same set for Dutch as for German.
- The registry comment, docs/development.md, the Dutch row and
  introduction of docs/localization-parity.md, and the interface
  languages line of docs/target-app-parity.md list Dutch among the
  languages that translate messages.
2026-11-13 01:23:19 -08:00
dotCooCoo 78ee4d04b6 Panels: item drags start only with the primary button, as Layers does
A right or middle drag on a swatch or color group, a brush, a symbol, a
graphic style, a library item or group, a character or paragraph style,
an Appearance row or thumbnail, the Fill and Stroke squares, a Recent
Colors chip or the Gradient panel's thumbnail started the same drag as
the primary button, so it could reorder, copy, delete or apply the item.
These drags now start only with the primary button, as Layers rows
(#7016) and Artboards rows (#7005) do: `widgets::drag_source`, the
Swatches tiles, library panel items, text style rows and Appearance rows
check `drag_started_by(Primary)`, and the Appearance thumbnail shows the
grabbing hand only for a primary drag. Right-click menus and the Graphic
Styles panel's held right-button preview are unchanged.
2026-11-13 01:22:30 -08:00
dotCooCoo 7805479dad Libraries: a character style's menu offers Apply, Add to Character Styles, Rename and Delete
A right-click on a character style in the Libraries panel now opens Apply
Character Style, Add to Character Styles, Move to Group, Rename… and
Delete. Apply is enabled only with type selected. Opening the menu applies
nothing, and the paragraph style menu is unchanged.

- library.addToCharacterStyles adds the style to the document's character
  styles without applying it, so no type needs to be selected. A document
  style with the same name and attributes is reused with no undo step, and
  a name taken by other attributes gets a number.
- library.renameItem renames a library item in place and keeps its group.
  The name is trimmed and has 1 to 256 characters. Another item of the same
  kind with that name is an error, the item's own name writes nothing, and
  a rename is not a document undo step.
- library.use and library.addToCharacterStyles compare a library style
  with the document's in the form the document stores it in. A whole
  number size from a library file no longer adds a numbered copy.
- A character style color linked to a swatch that is not a global or spot
  swatch of the document keeps the color it shows without the link.
  Before, adding or applying such a style failed with "no swatch".

Help page: https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/add-and-use-text-and-character-styles-in-libraries.html
2026-11-13 01:22:29 -08:00
dotCooCoo bc92def89e Smooth tool: smoothing a path deselects its direct-selected anchors
path.smoothRegion replaced the anchors of each path it smoothed but left
the selection alone, so anchor and segment refs selected with Direct
Selection still named the old indices: after a smooth that removed
anchors, a ref could point past the end of the path or at another
anchor. The edit now drops those refs for each path it changes, so the
path stays selected whole. Selected paths the drag does not change keep
their anchors, and undo restores the earlier selection.
2026-11-13 01:12:38 -08:00
dotCooCoo 6e2fe9fddf SVG: right-to-left text with text-anchor start or end opens at its directional edge
SVG 2 defines text-anchor start for right-to-left text as placing the
right side of the text at its position, and end as placing the left
side there (https://www.w3.org/TR/SVG2/text.html#TextAnchoringProperties).
Import placed start at the left edge and end at the right edge whatever
the direction.

- Point type and type on a path swap start and end when the effective
  direction is rtl. On a path, right-to-left text anchored by start now
  ends at startOffset and text anchored by end begins there. Vertical
  type keeps its anchoring.
- Each line and each absolutely placed chunk is anchored by the
  text-anchor and direction of the element holding its first
  character, a tspan's own included. A later chunk no longer takes the
  first chunk's anchor.
- Each line of point type starts at its own x, also when it has the
  same anchor as the line before it or another line holds absolutely
  placed characters. Such lines were drawn at the first line's x.
- A test covers letter-spaced right-to-left lines: the layout keeps the
  tracking of every letter in such a line, so the whole advance sits
  on its anchor.
2026-11-13 01:06:53 -08:00
BFlat 3b48070751 Merge pull request #7061 from dotCooCoo/fix/dcs-transparency-clip
Place: DCS transparency interactions look only at what clipping paths show
2026-11-13 16:04:49 +07:00
BFlat d118fcb17c Merge pull request #7046 from dotCooCoo/fix/issue-3349
.ai import: graphic styles of one paint open with their fill and stroke
2026-11-13 16:04:36 +07:00
BFlat f0653da969 Merge pull request #7072 from kler/swedish-ui-2026-11-13
i18n(sv): translate 37 new strings, use the agreed terms in 9
2026-11-13 16:04:26 +07:00
dotCooCoo 093f04952c Image Trace: Create Strokes makes a wide shape's thin features strokes and keeps its body a fill
Stroke is the widest feature that can be stroked, and it was applied to
each connected shape as a whole: a thick body with thin arms stayed one
filled area. Now a shape wider than Stroke somewhere keeps as its area
every disc wider than Stroke that fits in it, and each piece outside
those discs that reaches out of them at least one and a half times its
own width (and 3 px) is traced as a stroked center line. A line's end at
the area goes to the cut, so the line's cap closes the join. Corners and
edge slivers stay in the area, and a piece that cannot be traced stays
in it too. Shapes no wider than Stroke trace as before.

Each line keeps one width; without Fills, the area is still a 1 px
outline.

Docs: docs/target-app-parity.md.
2026-11-13 01:01:59 -08:00
Don Omondi ffc22ffc4c Merge remote-tracking branch 'upstream/main' into fix/graphic-styles-list-height-2992
# Conflicts:
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-13 03:20:58 -05:00
BFlat 9a1a158a3f Merge pull request #7060 from dotCooCoo/fix/dcs-regained-clip
Place: a DCS file that regains its clipping path clips the group that stayed
2026-11-13 15:04:28 +07:00
BFlat 46be3af7f8 Merge pull request #7064 from dotCooCoo/feat/envelope-warp-points
Envelopes: the Mesh tool and Direct Selection edit a warp envelope's points
2026-11-13 15:04:18 +07:00
BFlat 806dd5ef5b Merge pull request #7049 from dotCooCoo/fix/3d-face-budget-per-object
3D: an object's fill and stroke solids share one face limit
2026-11-13 15:04:08 +07:00
BFlat dd8446f3a4 Merge pull request #7054 from dotCooCoo/feat/nine-slice-guides-outside-art
Symbols: 9-slice guides may lie outside the symbol's art
2026-11-13 15:03:59 +07:00
Patrik LermonandClaude Opus 5.5 4e0b50bc9c i18n(sv): translate 37 new strings, use the agreed terms in 9
Brings the Swedish catalog up to date with upstream main (7d77f8aeb).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 08:40:41 +01:00
BFlat 8998d94cc8 Merge pull request #7057 from dotCooCoo/feat/paste-remembers-sublayers
Layers: Paste Remembers Layers puts art back into the sublayer it was copied from
2026-11-13 14:18:03 +07:00
BFlat 11a37082f7 Merge pull request #7058 from dotCooCoo/feat/touch-workspace
Touch: a two-finger tap switches between selection and drawing modes
2026-11-13 14:17:54 +07:00
BFlat 001660517c Merge pull request #7059 from dotCooCoo/fix/dcs-eps-proxy-plates
Place: DCS links reopen with their plates under the low-resolution EPS proxy
2026-11-13 14:17:44 +07:00
BFlat cc5a63d7dc Merge pull request #7062 from dotCooCoo/fix/para-style-options-height
Text styles: Paragraph Style Options keeps OK and Cancel on a small screen after a section switch
2026-11-13 14:17:31 +07:00
BFlat 7d417a0729 Merge pull request #7048 from dotCooCoo/fix/font-menu-shared-filters
Font menu: every font menu shares one set of filters
2026-11-13 14:17:18 +07:00
BFlat d0b4df357c Merge pull request #7063 from dotCooCoo/fix/ui-parity-pencil-fidelity-unit
Docs: the Pencil row gives Fidelity in screen pixels
2026-11-13 14:17:05 +07:00
BFlat 9ba02d41d7 Merge pull request #7038 from dotCooCoo/fix/schema-expected-phrases
i18n: parameter schema errors translate what the value must be
2026-11-13 14:16:56 +07:00
BFlat 77b0bbf1d3 Merge pull request #7066 from dotCooCoo/fix/package-scope-after-save
Package: a package started after its save keeps the automation roots
2026-11-13 14:16:46 +07:00
BFlat d5699579de Merge pull request #7017 from mockydevs/fix/pdf-empty-actualtext-art-6971
PDF import: glyphs in a span with an empty ActualText come in as outlines
2026-11-13 14:16:32 +07:00