Commit Graph
2329 Commits
Author SHA1 Message Date
Carbocode 0daecb7022 M1: keep sidebar field text in place on focus 2026-10-30 10:44:38 +01:00
BFlat 10c66678c3 Merge pull request #1641 from ChristopherLinnett/feat/1280-color-calculations
M3: colour variables can be calculated from others, faded or mixed per mode (#1280)
2026-10-30 16:16:23 +07:00
BFlat 99440fa9ff M8: a drag that only moves the selection shifts what was worked out at its start (#1571) (#1640)
The engine notes when a drag has only moved the selected layers by one offset (Interaction::moved_by); the canvas keeps the outlines, box and slots from the drag's start document and shifts them, the selection spacing and the Design panel's values (but the position fields) come from that document, and the Export section's values are kept. Dragging 648 layers: UI pass 2.10 to 1.44 ms a frame.
2026-10-30 16:13:55 +07:00
Christopher Linnett 8d5bad2afc M3: CSS export never names a calculation it leaves out either (#1280)
The CSS export left out a colour calculation that resolves to nothing but still wrote an alias to
it as var(--name); where no block defines that property, whatever reads the alias is invalid.
CSS (and Tailwind) and Penpot now share one rule, Variables::flattener: an alias that leads to a
calculation some mode of its collection leaves out goes out as the value it shows in the mode,
or is left out when it shows nothing.
2026-10-30 16:59:19 +08:00
BFlat 34fce9bfcf M12: create the next board shape already connected (#1631)
* M12: create the next board shape already connected (#1597)

A selected sticky or shape shows a + beside each side; hovering one previews where the next goes, clicking makes one of the same kind, size and colour there, joined by a connector, and starts typing in it, in one undo step. board.addConnected {id?, side?, edit?} does it from commands.

* M12: the connected-shape handle and command in every full catalog (#1597)

* M12: Shift+Cmd/Ctrl+Enter on a board shape adds the next one already connected (#1597)
2026-10-30 15:59:13 +07:00
bflatastic 68450a6a0e Merge main into #1641 2026-10-30 15:57:31 +07:00
BFlat d17de284da Tests: read the docs' examples whatever the checkout's line endings (#1645)
inspect_fields::compact_examples_run_verbatim_from_the_docs split docs/mcp.md and docs/control-protocol.md on text ending in a newline, so on a Windows checkout with core.autocrlf (CRLF docs) it panicked and cargo xtask ci failed locally. The test now reads both with LF line ends. Found while gating on Windows.
2026-10-30 15:53:33 +07:00
BFlat 74b69125b7 Merge pull request #1642 from kler/swedish-ui-2026-10-30
i18n(sv): translate 36 new strings
2026-10-30 15:50:39 +07:00
BFlat c1451fecd5 M4: an imported file finds an installed family under the other names its fonts give it (#1292) (#1628)
Fonts name a family by its typographic name and by a legacy name per weight; fonts without typographic names are installed under the legacy ones only. FontDb::resolve finds either from the other, and matches names across case, spaces, hyphens and underscores; every lookup (import, paste, REST import, rendering, missing fonts, the font report) uses it. A weight-number style goes by that weight, and .fig and REST imports wait for the installed fonts to be indexed.
2026-10-30 15:44:09 +07:00
BFlat 328bb6e269 Merge pull request #1609 from avhn/fix/1085-grouped-panic-rollback
M8: a grouped command whose closure panics leaves the document as before (#1085)
2026-10-30 15:27:30 +07:00
Christopher Linnett 55e5f31eb5 M3: document the colour-calculation functions this change touches (#1280)
Why type_of gives references no type, what display shows, how resolve_memo bounds one resolve,
and what variable.create and variable.set check before anything changes.
2026-10-30 16:25:26 +08:00
Christopher Linnett 1784567497 M3: Penpot tokens never reference a calculation a set leaves out (#1280)
A colour calculation that resolves to nothing in a mode is left out of that mode's token set, but
an alias to it still went out as a {name} reference to the missing token. Such an alias, and any
alias leading to one, now goes out as the colour it shows in the mode, or is left out with the
calculation's warning when it shows nothing. A calculation left out in only one mode of its
collection counts too: a reference to it from another collection would dangle whenever that
mode's theme is active.
2026-10-30 16:25:26 +08:00
Christopher Linnett bc76665c65 M3: colour variables can be calculated from others, faded or mixed per mode (#1280)
A colour variable's value in a mode can now be {"alpha": {"variable", "opacity"}} - that
variable's colour with its alpha replaced - or {"mix": {"from", "to", "t"}}, a per-channel blend
of two colour variables or literals over the stored values (in the document's colour profile),
alpha included. Calculations resolve lazily like aliases, so bound layers, mode switches,
instances and undo follow their sources; they compose, and a loop, or a calculation that reads
more than 32 variables in its collection's modes (other collections in their default modes), is
refused when it is set. Operands are stored by id and read by exact id, as stored references
are. Files keep them; REST, CSS, Penpot and .fig exports write the colour they show in each mode;
deleting a source leaves its readers on the colour they showed; library import and swap
re-point their operands. The Variables panel shows them with their formula and can swap one for
an alias or detach it to its colour.
2026-10-30 16:25:26 +08:00
BFlat 1772ecefb0 Merge pull request #1636 from ChristopherLinnett/fix/574-fig-import-large
M8: .fig import budgets four values per compressed canvas byte instead of one (#574)
2026-10-30 15:22:58 +07:00
Patrik LermonandClaude Opus 5.5 8dd69797af i18n(sv): translate 36 new strings
Brings the Swedish catalog up to date with upstream main (e94350a7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:19:45 +01:00
bflatastic 955f101221 Merge main into #1609 2026-10-30 15:12:01 +07:00
BFlat e94350a778 Merge pull request #1630 from samhyun/perf/partial-damage-margin
M8: an edit renders where the changed layer paints, its effects' margin once
2026-10-30 15:07:13 +07:00
bflatastic 027a0bbf92 Merge main into #1636 2026-10-30 15:06:33 +07:00
BFlat c44f382d71 Merge pull request #1633 from samhyun/fix/partial-backdrop-at-view-edge
M8: a patch reads no backdrop past the view's edge
2026-10-30 15:05:08 +07:00
bflatastic 7c8f2a929a Merge main into #1609 2026-10-30 14:52:57 +07:00
bflatastic e5a5da9e62 Merge main into #1609 2026-10-30 14:35:19 +07:00
bflatastic d9955fdc14 Merge main into #1616 2026-10-30 14:32:50 +07:00
BFlat 51f275b2ff Merge pull request #1420 from avhn/feat/996-inspect-fields
M0.9: inspect layer trees with selected fields or a compact outline (#996)
2026-10-30 14:31:33 +07:00
bflatastic 871ac24e6f Merge main into #1616 2026-10-30 14:29:56 +07:00
bflatastic 09e0e2dbfc Merge main into #1609 2026-10-30 14:29:18 +07:00
BFlat c8b0726d2d Merge pull request #1505 from markx77/fix/german-labels
M10: clarify German gradient, OpenType and startup labels
2026-10-30 14:18:18 +07:00
bflatastic e573652b17 Merge main into #1420 2026-10-30 14:14:34 +07:00
Christopher Linnett 1a454edd09 M8: .fig import budgets four values per compressed canvas byte instead of one (#574)
The .fig import gave a file one decoded value per byte of its compressed canvas (at least 20M, at
most 128M). Dense legitimate files decode past that, further since every scalar field counts, and
the whole import was refused as "not a valid FigCraft file: .fig file: message: too many values".
The budget is now four values per compressed byte; the floor and both ceilings (128M, 32M on 32-bit
targets) are unchanged, so a small file that unpacks past the floor is still refused and no file
decodes more values than the ceiling allowed before. Generated 21 MB and 15 MB canvases (220,044
and 108,012 layers) and a 49.7 MB one budgeted at the ceiling (530,106 layers) now open whole
without warnings; the 49.7 MB one's test peaks at about 9 GB.
2026-10-30 15:09:50 +08:00
bflatastic 58d791c887 #1616: take the image byte budget from IMAGE_BUDGET 2026-10-30 13:57:08 +07:00
bflatastic d0d79fdee5 Merge main into #1616 2026-10-30 13:57:06 +07:00
bflatastic 991ea891b5 Merge main into #1609 2026-10-30 13:56:15 +07:00
bflatastic c334853a6e Merge main into #1505 2026-10-30 13:53:42 +07:00
bflatastic 966f823551 Merge main into #1420 2026-10-30 13:52:53 +07:00
bflatastic 1c9aece79d Merge main into #1618 2026-10-30 13:52:02 +07:00
BFlat c47177498d M8: every file a command reads by path is a regular file within a cap (#1114) (#1625) 2026-10-30 13:48:26 +07:00
bflatastic 20ae99afff Merge main into #1505 2026-10-30 13:36:51 +07:00
bflatastic cf54d64a64 Merge main into #1420 2026-10-30 13:36:11 +07:00
bflatastic ad8bad3cc3 Merge main into #1618 2026-10-30 13:35:24 +07:00
BFlat 47e9e0a50d M8: a component set's property rows fit the 240 px right panel (#1629) 2026-10-30 13:32:36 +07:00
samhyunandClaude Opus 5.5 40f83a9a08 M8: a patch reads no backdrop past the view's edge
Background blurs and glass read the pixels drawn under them, and a full
render's backdrops end where the view does. The retained renderer differed
in two ways.

render_into drew each damage rect with a margin all round, past the edge
too, so a backdrop there read content a full render never drew: with a
background blur of 60 across the left edge, moving a square beside it
patched 10 levels off a full render, and moving one entirely off the view
89. The margin now stops at the edge.

A pan re-rendered only the strips it uncovered. At the opposite edges, which
moved into the old frame, the shifted pixels kept what their backdrop had
read past the old edge: a background blur of 10 across the view was 89
levels off after a pan of 30. Those edges are now redrawn as far as a
backdrop reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 15:26:36 +09:00
bflatastic a3c0de04a8 Merge main into #1505 2026-10-30 13:22:50 +07:00
bflatastic cf129e42c9 Merge main into #1420 2026-10-30 13:21:51 +07:00
samhyunandClaude Opus 5.5 a3d70d4c43 M8: an edit renders where the changed layer paints, its effects' margin once
paint_bounds, the area a change to a layer can affect, was its paint bounds
(effects included) grown again by effect_margin, what its effects read from
outside. Drawing an area already takes that in, as culling does, so the
damage of an edit near effects was counted twice: moving a 120 x 120
rectangle with a shadow falling 40 rendered 122,844 pixels for 56,876 it can
change, and edits that would fit a partial render fell back to full ones.

The retained test that a group's shadow had pushed past the partial share
gets its 300 x 220 view back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 15:10:49 +09:00
bflatastic b157a38e99 Merge main into #1618 2026-10-30 13:05:24 +07:00
BFlat 7b886404c3 M8: Opening a file contacts no team library server it names until you check it (#1621)
* M8: opening a file contacts no team library server it names until you check it (#1097)

* M8: translate the team library check strings (#1097)

* M8: the Assets panel library test checks what allows a library, without its own fake link (Sonar duplication and coverage)
2026-10-30 13:03:31 +07:00
BFlat 15479eacb8 Merge pull request #1626 from samhyun/fix/scaled-effect-reach
M8: effects reach as far under a scaled layer
2026-10-30 13:01:40 +07:00
bflatastic 67540b0197 Merge main into #1505 2026-10-30 12:51:34 +07:00
BFlat f1eaf3fcb4 M8: cap the people a client keeps track of and the deleted ids a session remembers (#1622)
* M8: cap the people a client keeps track of and the deleted ids a session remembers (#1121)

A hostile host or server could grow a client's presence, seen-peers and who-is-here lists without bound, and a session's deleted-id set only grew. Clients keep at most MAX_PEERS (4,096) others, leaving newcomers out with a warning; max_people is at most that; a session remembers at most 262,144 deleted ids, the lowest forgotten first.

* M8: a max_people above what clients track is lowered with a warning, not refused (#1121)

Refusing it would stop a server whose existing config says more from starting after an upgrade. Config::people() lowers max_people to MAX_PEERS for the core's limits, and the startup warnings name the configured and the used value.

* M8: the live welcome's handling in its own function (Sonar S3776)
2026-10-30 12:33:29 +07:00
Dylan M. Taylor 0b7528b76d Update prompt shows the app icon and accent color instead of a letter (#1612)
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#02da96, its colour in ArtCraft Launcher). The updater, the self-update
helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the
prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer).

craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434).
2026-10-30 01:28:14 -04:00
Markus Reimr 7996de560c M10: merge current main and resolve German PR conflicts 2026-10-30 06:24:55 +01:00