Commit Graph
3465 Commits
Author SHA1 Message Date
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
BFlat b2885452fb M8: doc.list gives AI agents and plugins file names, not paths (#1117) (#1620) 2026-10-30 12:14:34 +07:00
samhyunandClaude Opus 5.5 07c936f560 M8: PR #1626 review: tiny scales and pixel-spread layers
local_reach gave up on transforms whose determinant was under 1e-12 and
kept the reach in page units, so a layer scaled to a ten millionth (a
billion units drawn 100 wide) had its shadow cut (245 levels). It now
converts any finite, non-zero scale, capping the result where the sums
would overflow.

Groups and stroked text spread their shadows as pixels, in page units:
their spread no longer also counts in local units.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 14:12:58 +09:00
BFlat 5247f73f59 M8: a large selection's overlay and Design panel values are kept for frames where nothing changed (#1611)
* M8: a large selection's overlay and Design panel values are kept for frames where nothing changed (#1571)

The selection's outlines, box, size and slots on the canvas, and the Design panel's instance checks and position values, are kept with the document snapshot (held weakly), the selection and, for the overlay, the view's mapping to the screen and the overlay green, and made again when any changes. Dragging 648 selected layers: overlays 1.99 to 0.86 ms a frame, Design panel 2.54 to 1.40 ms.

* M8: split the position fields into one function per row (Sonar S3776)
2026-10-30 11:54:44 +07:00
BFlat 7d18fa391b M8: libraries and plugins larger than the download burst can be downloaded, more slowly (#1089) (#1619)
The per-address download bucket never held more than its 16 MiB burst, so a larger library or plugin was refused for good. Bucket::take_spread serves one from a full bucket and leaves the debt to refill at the rate before the next download; the rate over time still holds.
2026-10-30 11:39:51 +07:00
BFlat 24cf643254 M8: a batch keeps one undo snapshot, not one per step (#1099) (#1610) 2026-10-30 11:22:06 +07:00
cc0976a4a2 #1609: a grouped panic keeps its payload and lets later live edits sync
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
2026-10-30 07:13:03 +03:00
Mert Dede 1c4201f48a Merge remote-tracking branch 'origin/main' into fix/1613-stored-variable-ids
# Conflicts:
#	docs/roadmap.md
2026-10-30 07:08:06 +03:00
Mert Dede 415e83814f Merge remote-tracking branch 'origin/main' into fix/1076-fig-image-budget
# Conflicts:
#	ROADMAP.md
#	docs/file-format-parity.md
#	docs/roadmap.md
2026-10-30 07:08:02 +03:00
Mert Dede 3a59a70b10 Merge remote-tracking branch 'origin/main' into fix/1085-grouped-panic-rollback
# Conflicts:
#	docs/roadmap.md
2026-10-30 07:07:56 +03:00
Mert Dede 5c3aef840a Merge remote-tracking branch 'origin/main' into feat/996-inspect-fields
# Conflicts:
#	docs/roadmap.md
2026-10-30 07:07:54 +03:00
BFlat 4224f4b660 M8: deep files import on the browser's 1 MB stack (#1101) (#1600)
The REST import's layer walk (also the .fig import's second stage) took about 4 KB of stack a level, a megabyte at the 256-level cap, and overflowed a 1 MB thread. It now runs on a work list in the same order, fitting groups once their children are in. The .fig mapping stays recursive at about 1.8 KB a level (455 KB at the cap). Both 256-deep imports now run on a 1 MB stack; the cap stays 256 everywhere.
2026-10-30 11:04:57 +07:00
2f47014917 M3: stored variable and collection references keep their identity (#1613)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Co-Authored-By: GPT-6.1 Terra <noreply@openai.com>
2026-10-30 06:49:06 +03:00
fcde83a5a6 M8: .fig ZIP image reads share a total byte budget (part of #1076)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Co-Authored-By: GPT-6.1 Terra <noreply@openai.com>
2026-10-30 06:49:05 +03:00
BFlat 7fdbda9f09 M8: One depth cap for a whole render, and render threads with room for it (#1605)
* M8: one depth cap for a whole render; render threads get 8 MiB stacks (#1082)

A pattern fill drew its source as a fresh render from depth 0, so patterns in patterns could stack three renders of 256 levels. The source now goes on from the depth of the layer it fills. A render level takes about 6.5 KB of stack (measured), about 1.7 MB at the cap: the canvas render, preview and save threads and a band pool of their own now get 8 MiB stacks instead of the default 2 MiB.

* M8: SVG and PDF exports carry the depth into pattern sources and embedded renders (#1082)
2026-10-30 10:43:49 +07:00
samhyunandClaude Opus 5.5 0df9189750 M8: effects reach as far under a scaled layer
The renderer draws drop shadows, layer blurs and texture at their size in
page units however a layer is transformed, but sized a layer from its local
box grown by the effects' reach in local units, so under a transform that
scales down the effect was cut (245 levels on the canvas, exports holding
half to 60% of the paint).

bounds_within now takes the layer's local-to-page map and turns the reach
into local units per axis. A drop shadow's spread of a filled outline is the
exception: the outline is grown before it is transformed, so that part
follows the layer's scale. Layer bounds and own_paint_bounds take, per
shadow, the larger of the two readings, so an unscaled layer comes out as
before; exports of scaled-up spread shadows, which were cut, now hold them,
and so do the corners of a turned rectangle's spread. The mitre reach is
clamped like the other reaches, so a huge spread no longer makes bounds NaN.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 12:03:28 +09:00
bflatastic e79afdce67 Merge main into #1608 2026-10-30 09:57:22 +07:00
9573b8b2d2 M8: a grouped command whose closure panics leaves the document as before (#1085)
A panic in a Session::grouped closure outside any command skipped the group rollback: the
documents stayed half edited, the history limit unbounded, live documents held and the group
depth raised. checkpointed now catches the unwind, runs the same rollback as a failed group and
resumes the panic, so the caller's guard still reports it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
2026-10-30 05:54:31 +03:00
BFlat e274279587 M8: one unpack budget per .figcraft open (#1079) (#1599)
Each area (document, images, library, versions, branches) keeps its own cap and now also draws from one total per file open, 6 GiB (2 GiB on 32-bit targets), so a file can no longer make the app unpack about 10 GB. Read in that order, the document and the images up to their own cap fit, so a file whose images pass 4 GiB (#1313) keeps as many as before; images left out by the total stay in the file like those past the image cap. What passes the total is skipped (the document refused) with a note.
2026-10-30 09:44:47 +07:00