21 Commits
Author SHA1 Message Date
Trevor Brown cc4fcd5827 Merge remote-tracking branch 'upstream/main' into fix/geom-bounded-sizes
# Conflicts:
#	crates/geom/src/lib.rs
2026-11-06 23:48:15 -05:00
BFlat 7da396e1b3 Merge pull request #2067 from storytold/carry/1942
fix(geom): keep arc subdivision bounded whatever the radius
2026-11-07 12:14:07 +08:00
BFlat 1eef98d610 Merge pull request #1797 from TheGalitube/fix/h7835-large-decimal-precision-makes-ro
Preserve finite values at large rounding precision
2026-11-07 12:03:46 +08:00
bflatastic f1a5360859 Merge main into #1942 2026-11-07 10:54:18 +07:00
BFlat e9fc975aa6 Merge pull request #1756 from dotCooCoo/feat/vector-network-corner-smoothing
M4: closed vectors take corner smoothing
2026-11-07 10:27:00 +08:00
Dylan M. Taylor 411b16931b fix(geom): keep arc subdivision bounded whatever the radius
kurbo turns an arc into cubics by radius divided by tolerance, so the fixed
0.01 let an ellipse, polygon corner, rounded rectangle, per-side stroke
corner or SVG arc with a radius like 1e300 ask for more cubics than memory
holds before any size check saw the geometry. Arcs now use a tolerance
that scales with the radius, and SVG path data from documents, commands and
imports is refused before parsing when a number passes 1e9.
2026-11-03 15:45:48 +00:00
Trevor BrownandClaude Fable 5.1 a6e7920b24 Geometry: measurement allows a capped arc's control points past the cap
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-02 03:50:41 -05:00
Trevor BrownandClaude Fable 5.1 5c34af35f8 Geom: the measurement bound includes the cap, as the builders clamp to it
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-02 02:00:21 -05:00
Trevor BrownandClaude Fable 5.1 6e78b7270c Merge upstream main into fix/geom-bounded-sizes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-02 01:33:31 -05:00
김삼현andClaude Opus 5.5 264bcb1c03 M8: an arc's spread shadow and mitred stroke get room for their corners (#1802)
* M8: an arc's spread shadow gets room for its mitred corners

Rectangles, frames and ellipses grow by exactly their spread, so their
layers only make room for the spread itself; other shapes make room for
the mitre at sharp corners (up to four times the spread). An ellipse
with arc data (a pie slice, or a ring cut short) counted as an ellipse,
but its ends meet its sides in sharp corners: a spread of 25 on a slice
of 0.3 rad cut its shadow off at the layer's edge (up to 255 levels).

Only an ellipse that goes all the way round now grows by exactly its
spread. `figcraft_geom::full_sweep` is what `ellipse` already used to
tell a whole ellipse or ring from an arc, so the two agree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* M8: an arc's mitred stroke gets room for its corners too

Review: `outline_reach` counted every ellipse as an outline whose stroke
mitres end on the grown box, the same mistake as the spread. A thin
slice with a 20-unit mitred stroke and a spread of 10 still had its
shadow cut off (255 levels). It now asks `grows_by_exactly_its_spread`,
which picks the same shapes and leaves arcs out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:12:27 -05:00
Max MittelstädtandGPT-5.6-Luna a46e2369bc Preserve finite values at large rounding precision
Found while testing crates/geom/src/transform.rs:59

Co-Authored-By: GPT-5.6-Luna <noreply@openai.com>
Co-Authored-By: GPT-6-Luna <noreply@openai.com>
2026-11-01 09:31:20 +00:00
Trevor BrownandClaude Fable 5.1 33f32c1166 Geom: the bounded-sizes test also covers the cap itself, NaN, infinities and negative sizes
Review follow-up on #1774.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-01 00:14:06 -04:00
Trevor BrownandClaude Fable 5.1 8e6a04baf6 M8: shape builders cap sizes, radii and angles at 1e9, so an absurd value cannot build millions of segments
Found while testing crates/geom/src/lib.rs (no existing issue): the builders replaced NaN and infinities with 0 but took any finite size, and kurbo subdivides an arc in proportion to the sixth root of its radius, so ellipse(1e36, ...) built about a million cubics and 1e60 never returned (sizes arrive from files and commands). The sanitizer now also clamps magnitudes to MAX_COORD (1e9, the bound measure::finite_path already uses). Polyline::nearest returns None for a non-finite point instead of Some((NaN, NaN)). Tests cover 1e36, 1e300 and f64::MAX for every builder.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-31 11:27:13 -04:00
dotCooCoo 000d39b042 M4: closed vectors take corner smoothing
A vector's corner smoothing was stored, imported and exported, but its
rounded points were drawn as plain circular arcs, and the Design panel
hid the Corner smoothing control for vectors.

A vector with a closed region now draws its rounded points with the
layer's corner smoothing, on the canvas, in hit testing, in PNG, SVG and
PDF exports, and in the fill and stroke geometry of .fig exports. Each
point keeps its own radius; a point without one stays sharp. The corner
uses the profile of smoothed polygon corners, and smoothing is reduced
before the radius when a corner does not fit in half of each segment.

FigCraft's own rules for cases the help page does not describe: only a
point between two straight segments that both bound a closed region is
smoothed; points on open branches and points next to a curved segment
keep the plain arc; concave corners are smoothed like convex ones.

The Design panel shows Corner smoothing and its iOS (60%) button for
vectors with a closed region, and not for open paths.
2026-10-31 02:33:38 -07:00
dotCooCoo 811d599960 M4: corner smoothing on polygons and stars
Polygon and star outlines did not use their corner smoothing: the value
was stored, imported and exported, but `shape_path` drew their corners
as plain circular arcs, and the Design panel showed the Corner
smoothing field only for rectangles and frames. Rounded polygon and
star corners now take smoothing the way rectangle corners do. Each
corner keeps a circular arc over the unsmoothed part of its turn and
eases into both edges, and it starts (1 + smoothing) times the plain
corner's length from the vertex. When a smoothed corner does not fit
in half of its shorter edge, smoothing is reduced first, then the
radius, as for rectangles. The Individual corners button opens the
panel for polygons and stars too, with the Corner smoothing row and no
field per corner.
2026-10-24 07:22:36 -07:00
a1a842af9a chore: resolve SonarCloud maintainability issues (#1241)
* chore: resolve SonarCloud maintainability issues

- Define SHA256_FMT constant in packaging script to remove duplicated string literal (shelldre:S1192)
- Remove redundant 'static lifetime annotations from const items (rust:S8863)
- Replace closures with method and function pointers (rust:S1612)
- Extract helper functions in synthetic document generation, bezier polyline flattening, and component restoration to reduce cognitive complexity (rust:S3776)

* fix(packaging): use verify_sha256 helper function to avoid shellcheck SC2059

* fix(engine): remove duplicate closing brace in large_document

* fix(engine): take &mut Document in restore_id_map; keep 'static on associated consts

restore_id_map allocates ids, so it needs a mutable document. Elided
lifetimes in associated consts trip elided_lifetimes_in_associated_constant,
so those annotations are restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assign positional parameters to locals in sha256 verification

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:13 -04:00
NetterSilverandClaude Haiku 5.5 2e12bdfd91 Keep open subpaths open in ReverseSubpaths::reverse_subpaths
Found while testing crates/geom/src/lib.rs:287

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-21 02:46:23 +02:00
Saad Abdullah 01904ce2fd fix(geom): enforce the path sample limit while flattening (#217)
The sample budget is enforced while a path is flattened, not after: the element count is checked up front, each curve is flattened on its own, and flattening stops as soon as the budget is exceeded. Fixes #204.
2026-10-14 03:26:11 +07:00
BFlat 894f25c4c4 M1: selection and transform behaviour suite and fixes (#133)
A selection and transform behaviour suite derived from public documentation, with fixes: Alt-resizing shrinks as well as grows; groups, Scale-constrained frames and multiple selections resize each layer along its own axes keeping rotation and flip; several layers flip together past an edge; a flipped layer reads back the typed rotation; resizes land on whole pixels with the pixel grid; presses inside tiny layers move them; locked layers get no handles; a marquee can start on a top-level frame's background; select inverse skips hidden layers. Adds equal-spacing snapping with labelled gaps and Cmd/Ctrl to ignore constraints while resizing a frame.
2026-10-11 20:30:38 +07:00
BFlat f62cb4b1f6 M4: text on a path and pattern fills (#118)
Text layers can follow a path (start offset, flip, alignment; edited in place; canvas, PNG, SVG, PDF; SVG textPath imports as real text on a path). A new pattern paint tiles a source layer in grid or hex rows with scale, spacing and alignment, live as the source changes (SVG pattern, PDF vector tiling pattern).
2026-10-11 13:25:33 +07:00
Brandon ThomasandClaude Opus 5.5 f7a68c864b M0.1-M0.3: workspace, licences, geom/color/doc crates
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:01:57 -04:00