Commit Graph
8337 Commits
Author SHA1 Message Date
dotCooCoo ed3efcbd7d Render: a long dashed stroke is outlined only near the view after an edit
A dashed stroke of a path with more than 1,024 path elements was outlined
whole in every frame after an edit. It is now outlined in and around the
view like a solid stroke. dash_kept runs the pattern along every segment
and keeps only the dashes and dots on the segments near the view, so they
sit where dashing the whole path puts them and the pixels are the same.
A pattern too fine to draw is still drawn solid, and that solid stroke is
cropped too.

At 1600 x 1200 the frame after one anchor moves takes 14 ms instead of
102 ms on a filled closed path of 50,000 anchors with 6 pt dashes and
4 pt gaps. anchor_bench now includes that document.
2026-11-05 03:55:48 +07:00
BFlat a2e98ac57c Merge pull request #5686 from ruchirguitar/fix/5336-optical-kerning-reference-gap
Fix #5336: Optical kerning spaces pairs by the font's own stem spacing
2026-11-05 03:30:17 +07:00
BFlat b402013f06 Merge pull request #5685 from dotCooCoo/fix/quick-bounds-nested-nine-slice
Symbols: quick boxes hold art that nested 9-slice guides move
2026-11-05 03:30:00 +07:00
BFlat 34b1fc9f42 Merge pull request #5681 from dotCooCoo/feat/recovery-folder-choose
Preferences: Data Recovery's Folder gets a Choose button
2026-11-05 03:29:45 +07:00
BFlat 23f56b6cfa Merge pull request #5682 from dotCooCoo/fix/share-of-thousands-comma
Numeric fields: 1,000% in a size field is refused
2026-11-05 03:29:20 +07:00
ruchirguitarandClaude Opus 5.5 b87fddba11 Type: Optical kerning spaces pairs by the font's own stem spacing (#5336)
Optical moved every pair all the way to a fixed 0.08 em ink gap, tighter
than most text faces' own stem spacing, so ordinary text was squeezed
(at 100 pt, Source Sans 3 `nn` closed from 54.7 to 46.9 pt).

Each pair now moves 0.6 of the way toward the face's reference gap (the
median ink gap of `nn`, else `HH` or `oo`; 0.08 em when it has none),
keeps at least 0.3 of it at its narrowest, and changes by at most
0.12 em tighter or 0.06 em looser. Ideographs, kana, hangul, fullwidth
and CJK punctuation forms and dashes keep the font's spacing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 03:04:51 +07:00
dotCooCoo 84c197cfbe Symbols: quick boxes hold art that nested 9-slice guides move
An instance of a symbol whose art holds a 9-slice instance draws that
instance through its guides with the transform of every instance above
it. When the outer symbol has no guides, the quick box of an outer
instance that scales or turns its art was its art box placed by its
transform, and the renderer could cull art the nested guides move past
that box.

Symbol art boxes now record whether the art holds an instance of a
symbol with 9-slice guides at any depth. For such art, quick boxes
place the art by the instance's transform and measure it, once for each
symbol and linear part. One set of boxes places at most
MAX_SYMBOL_NODES objects this way, the art of opacity masks included.
2026-11-05 03:04:48 +07:00
dotCooCoo 08aa511252 Preferences: a recovery folder that can't be listed is refused
Data Recovery lists the folders in its recovery folder before it starts, so a
folder that can be written but not listed (a Unix folder with mode 0333) left
it unable to start. Choose... now lists the picked folder as well as making a
folder in it, and refuses it with a status message when either fails. The
progress line says what is checked.
2026-11-05 03:04:39 +07:00
dotCooCoo 13d0cbc51f Preferences: the recovery folder check makes a folder, and a pick survives a closed document
The Choose... check now creates and removes an empty folder in the picked
folder, as the recovery store makes its own folder there, and reports a
folder it cannot remove again. The folder picker's answer fills the open
Preferences dialog even when the active document closed while the picker
was open, since the recovery folder is an app preference.
2026-11-05 03:04:39 +07:00
dotCooCoo 9613bfb31d Preferences: Data Recovery's Folder gets a Choose button
File Handling > Data Recovery > Folder has a Choose... button on the
desktop that opens the folder picker and puts the chosen folder in the
field. Cancel leaves the field as it was, and the field stays editable.
A chosen folder that no file can be created in is refused with a status
message. The web build has no folder picker, so the button is not shown
there.
2026-11-05 03:04:39 +07:00
dotCooCoo 3e96d59fd8 Numeric fields: 1,000% in a size field is refused
A percentage typed alone in a size field (W, H and the other fields
that take a share of their value) read its decimal comma before the
`%` was dropped. The thousands check then saw `1,000%`, and the comma
was read as a decimal point, so `1,000%` set the size to 1% of its
value. `share_of` now reads the decimal comma after dropping the `%`:
`1,000%` is refused, and `12,5%` still reads as 12.5%.
2026-11-05 03:04:35 +07:00
BFlat 58b445f27a Merge pull request #5683 from storytold/fix/planar-faces-cover-regions
Pathfinder: holes that touch at a point stay holes of their region
2026-11-05 03:02:21 +07:00
bflatastic b814fcf689 Pathfinder: holes that touch at a point stay holes of their region
The Live Paint faces were right; the Pathfinder regions over-counted.
Two small circles inside a big one, touching each other at one point,
gave the big circle's region only one of its two holes, and the other
hole came out as a region of its own.

linesweeper walks the boundary of the two touching holes as one loop
and, when the walk comes back to the shared point, cuts the second
hole off as a child of the first and flags it outer, as if it were an
island inside it. face_groups trusted that flag, so the hole started a
face. The same cut goes wrong the other way when an outer contour
touches its own hole: the outer contour comes out as an island inside
the hole.

Such a loop winds the same way as the contour it was cut from, against
its flag. face_groups now checks every contour's flag against its
winding; a pass where any disagrees is grouped by geometry instead
(each hole goes with the smallest outer contour of its mask around it).
Passes where they all agree keep the sweep's tree as before, at the
cost of one area per contour.

Adds deterministic tests for both shapes of the bug and checks in the
proptest regression seed.
2026-11-05 03:02:03 +07:00
BFlat 959662fde6 Merge pull request #5680 from dotCooCoo/fix/styled-text-paste-after-edit
Preserve styled text after copying a Type range
2026-11-05 02:38:33 +07:00
BFlat b145264150 Merge pull request #5679 from dotCooCoo/fix/place-tests-scan-handshake
Tests: the link-watch and place tests wait for the link scan instead of sleeping
2026-11-05 02:38:18 +07:00
BFlat bc54bbd594 Merge pull request #5678 from MMexicann/fix/xtask-prerelease-leading-zeros
Tooling: reject numeric prerelease leading zeros
2026-11-05 02:38:02 +07:00
BFlat df1cab1403 Merge pull request #5676 from dotCooCoo/fix/vertical-overflow-glyph-probe
Glyphs: overflowing vertical type keeps a chosen default glyph
2026-11-05 02:37:47 +07:00
dotCooCoo cd71257ac4 UI-5636: Preserve styled Type-range copies on canvas paste 2026-11-05 02:23:51 +07:00
dotCooCoo a5157654f4 Tests: the link-watch and place tests wait for the link scan instead of sleeping
The link-watch worker now signals a condition variable when it ends,
whether it stored its stamps or unwound, and Session::wait_link_scan
blocks until then. The place tests' idle helper waits on it once per look
in place of a 5 ms sleep under a 20 s wall-clock bound, and the engine's
link-watch and link-path tests wait on it in place of spinning under a
10 s bound. The link-watch tests date a rewritten file 2 s after the one
it replaces instead of sleeping 30 ms before writing it.
2026-11-05 02:23:48 +07:00
Andreas Haraminac 08bd77054d Tooling: reject numeric prerelease leading zeros 2026-11-05 02:23:44 +07:00
dotCooCoo 440b3b7444 Glyphs: overflowing vertical type keeps a chosen default glyph
Squashed from #5676 onto main.
2026-11-05 02:23:42 +07:00
BFlat f10ab42c05 Merge pull request #5674 from dotCooCoo/fix/glyph-grapheme-probe
Glyphs: a character with a combining mark reports the glyph it is drawn with
2026-11-05 02:20:20 +07:00
dotCooCoo b0d1ca4419 Glyphs: a character with a combining mark reports the glyph it is drawn with
text.setGlyphAlternate looked for the character's glyph only in a
cluster as long as the character. A character followed by a combining
mark is shaped in one cluster with the mark, so the lookup found
nothing: under a substituting feature such as salt, `gid: null`
reported the default glyph instead of the one drawn, and a request for
the default glyph changed nothing.

The lookup now also takes a cluster that holds the character's
grapheme, and in a cluster of several glyphs takes the character's
default glyph or one of its alternates. Text that overflows its area
is shaped with the whole grapheme.
2026-11-05 01:56:16 +07:00
BFlat 18490471a1 Merge pull request #5672 from dotCooCoo/fix/perceptual-pdf-help-cmyk-stops
Gradient: Perceptual PDF help counts stops as written, CMYK documents included
2026-11-05 01:43:29 +07:00
dotCooCoo 584b9706cc Gradient: Perceptual PDF help counts stops as written, CMYK documents included
The method help of paint.editGradient and docs/mcp.md said a Perceptual
gradient with spot stops becomes an image in PDF unless every other stop
is paper white, CMYK or gray. PDF export checks each stop's color as it is
written: a CMYK document, or an export that converts colors to a CMYK
destination profile, writes RGB and Lab stops in CMYK, so the gradient
becomes a DeviceN shading. Both texts now say so, and a test covers the
CMYK document and CMYK destination cases.
2026-11-05 01:31:24 +07:00
BFlat 66664020b0 Merge pull request #5671 from dotCooCoo/fix/package-status-fonts-background
Package: name every font left out when no dialog is shown
2026-11-05 01:30:38 +07:00
dotCooCoo bfe81407bc Package: name every font left out when no dialog is shown
A package written in the background that finished while another dialog
was open showed no Package created dialog, but its status line still cut
the list of fonts left out at 500 bytes, so the fonts past the cut were
named nowhere. The status line now cuts the list only when the dialog is
shown.
2026-11-05 01:22:06 +07:00
BFlat 487808cea6 Merge pull request #5670 from dotCooCoo/fix/kerning-parenthesized-thousands
Character: Kerning refuses (1,000) instead of reading it as 1
2026-11-05 01:17:23 +07:00
BFlat 091bd79a4e Merge pull request #5669 from dotCooCoo/fix/cmd-space-tool-drag-cursor
Keep drawing cursor during mid-drag Cmd+Space
2026-11-05 01:17:06 +07:00
dotCooCoo d4f3ec6c96 Character: Kerning refuses (1,000) instead of reading it as 1
field_number read a decimal comma before it dropped Kerning's pair of
parentheses, the suffix, % and degrees, so the thousands check saw
(1,000) and 1,000% and read the comma as a decimal point: (1,000)
committed 1. The comma is now read after those are dropped, so
(1,000), 1,000% and 1,000 degrees are refused as 1,000 already is,
while (1,5) and 12,5% still read as 1.5 and 12.5.
2026-11-05 01:08:30 +07:00
dotCooCoo 7f449cc3c8 UI-1628: Keep drawing cursor during mid-drag Cmd+Space 2026-11-05 01:08:26 +07:00
BFlat cd9f4d5320 Merge pull request #5668 from dotCooCoo/fix/tabs-unchanged-ends-typing
Tabs: setting the stops a paragraph already has ends the typing session
2026-11-05 01:07:37 +07:00
BFlat 4a21936339 Merge pull request #5667 from storytold/about-credits-refit-inputs
About: refit credits tables on what they measure
2026-11-05 01:07:21 +07:00
dotCooCoo be8438c13d Tabs: setting the stops a paragraph already has ends the typing session
text.tabs.set and text.tabs.clear return without an edit when every
targeted paragraph already holds the stops. That path skipped the
settlement Session::edit does first, so a typing session in progress
stayed open. The command now ends it first, as the Variables commands
do: the typing is its own undo step whether or not the stops change.
2026-11-05 00:55:35 +07:00
FredAppsandClaude Opus 5.5 178e4a00df Refit credits tables on what they measure, not the fitted widths
Comparing the fitted widths missed the case it was meant for. Name is the
only growing column, so a longer name takes its extra width from the
spare room and the fit comes out the same: a dragged Name width stayed,
clipping the longer name.

It could also drop dragged widths by accident. The fit comes from the
available width inside the scroll area, which scrolling can nudge, so
scrolling a widened table could reset it.

The table now compares the natural widths and the clip rect's width,
which scrolling does not move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:55:32 +07:00
BFlat d7690eba02 Merge pull request #5665 from d8abyte-dk/plugins-compound-guide-filter-and-color-profile
Plug-ins: compound guides aren't filter inputs; colors follow the working RGB space
2026-11-05 00:54:38 +07:00
d8abyte-dkandClaude Opus 5.5 ad93abd484 Plug-ins: compound guides aren't filter inputs; colors follow the working RGB space
A compound path a filter made a guide was still given to later filters, which
could change or delete it; compound paths of guide paths are now left out as
guide paths are. Hex colors and the color button's choice are display sRGB and
are now converted into the working RGB space, so they show as given whatever
the working profile; a color default is kept as written and read when used.

Follow-up to #5630.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:42:23 +07:00
BFlat a0ef97af40 Merge pull request #5664 from Janiz-zzz/fi-update-20261103
i18n(fi): translate the 5 labels Finnish lacks
2026-11-05 00:41:17 +07:00
Janiz-zzzandClaude Opus 5.5 28a46e96c7 i18n(fi): translate the 5 labels Finnish lacks
Check for Updates and its window, the panel-layout reset notice and the
Image Trace progress lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:32:31 +07:00
BFlat 7bb95a901a Merge pull request #5662 from ruchirguitar/fix/5548-plain-click-keeps-hidden
Select by Artboards dialog: a plain click keeps artboards the search hides
2026-11-05 00:24:59 +07:00
ruchirguitarandClaude Opus 5.5 7f3d2b6406 Select by Artboards dialog: a plain click keeps artboards the search hides (#5548)
A plain click chose only the clicked row and dropped artboards chosen
but hidden by the search. It now replaces only the rows shown, as None
and Select All already do, so hidden rows keep their state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:16:17 +07:00
BFlat 020275520c Merge pull request #5659 from dotCooCoo/fix/color-mode-rgb-spot-test
Tests: an RGB spot color converts with Document Color Mode and stays spot
2026-11-05 00:11:04 +07:00
BFlat c85b41a9dc Merge pull request #5657 from dotCooCoo/fix/glyph-alternates-default-and-graphemes
Glyphs: the default glyph can be chosen back under a substituting feature
2026-11-05 00:10:49 +07:00
dotCooCoo f026ebe686 Tests: an RGB spot color converts with Document Color Mode and stays spot
A spot swatch defined in RGB keeps its spot flag and its own plate when
the document changes to CMYK, and its definition converts like any other
swatch: a fill that uses it and a 40% tint stroke take the converted
color. The Lab spot test's comment now says it covers a Lab definition.
2026-11-04 23:58:58 +07:00
dotCooCoo fae49d31fd Glyphs: the default glyph can be chosen back under a substituting feature
Follows #5442.

- text.setGlyphAlternate keeps the default glyph as a choice when a
  feature of the character's style (salt, a stylistic set) draws another
  glyph for it, so the default glyph is drawn. A character that is not
  laid out (overflowing text) is shaped alone in its style to decide.
  gid: null reports the glyph the style draws.
- The Glyphs panel's alternates grid shows the default glyph first when
  the font does not list it, so a chosen alternate can be put back.
- A test for a chosen character that starts a longer grapheme (f with a
  combining acute), which is not split from its mark.
- The alternates tests in the engine hold the shared font lock while
  they add fonts to the global font database.
2026-11-04 23:58:54 +07:00
BFlat 285ce2d2e0 Merge pull request #5656 from dotCooCoo/fix/png-reader-growth-room
Images: a PNG read a row at a time counts the reader's buffer while it grows
2026-11-04 23:58:04 +07:00
BFlat 90f5e5714b Merge pull request #5655 from dotCooCoo/fix/control-bar-inline-fields-fit
Control bar: the inline X, Y, W and H fields show only when they fit
2026-11-04 23:57:48 +07:00
BFlat 1463f86ec4 Merge pull request #5652 from dotCooCoo/fix/add-new-item-comment
Appearance: Add New Fill and Add New Stroke comment names the paint they take
2026-11-04 23:57:30 +07:00
BFlat 488d37f3ab Merge pull request #5653 from dotCooCoo/fix/nativemenu-font-scan-race
Tests: native menu tests wait for the installed fonts' scan
2026-11-04 23:57:15 +07:00
dotCooCoo 0a65178696 Images: a PNG read a row at a time counts the reader's buffer while it grows
The png reader's stream buffer grows by doubling its reservation, and
while it grows the old reservation and the new one are both allocated.
The room estimate counted the buffer twice, for the doubled
reservation, but not the moment both are held, so a wide PNG could be
approved for a row-at-a-time decode with less room than reading it
takes. The estimate now counts the stream buffer three times.
2026-11-04 23:45:05 +07:00