Commit Graph
27 Commits
Author SHA1 Message Date
BFlat fdb5ef4aa0 Merge pull request #2081 from TrevorBrown-dev/fix/ellipse-four-anchors-2080
Ellipse: an unsliced ellipse edits as four anchor points, not six (#2080)
2026-11-12 09:55:56 +07:00
bflatastic b1ee6535c9 Ellipse tests: drop an unused binding and a comment about an allowance main never had 2026-11-12 09:23:03 +07:00
ljkx 61389cdd5f M4: test the simplified stroke by how far it strays, at more accuracies and inputs (#1741)
Review follow-ups, tests only.

- The Pencil test and the `vector.simplify` test measure how far the result
  strays from the samples (at most 1.5), not only its box.
- The Pencil test also draws with the Marker and the Highlighter, each stroke
  in a fresh session, and takes the layer that stroke made.
- The `vector.simplify` test runs on an open stroke, a filled shape, a region
  with its own fill, and a stroke beside a filled shape.
- The geom tests run at accuracies 0.1, 0.75 and 8.0, on quadratic and cubic
  inputs as well as lines, and check both ways round how far the result and
  the input are apart.
- A path that turns straight back is checked to be kurbo's fit of each side on
  its own, with a point at the turn.
- Empty paths, lone moves and segments after a close are covered.
2026-11-09 21:51:37 +01:00
ljkx 0aba3f7632 M4: a Pencil stroke stays where it was drawn, without spikes off it (#1741)
kurbo's simplify_bezpath, which smooths Pencil samples and runs Simplify
path, fitted two common shapes with a curve that ran far off the path: a
stroke that goes out and back to the very point it left (kurbo keeps a
reversal as a smooth join) and nearly collinear samples (kurbo measures
its error across the path, not along it).

figcraft_geom::simplify_path cuts the path where it turns back by more
than a right angle, simplifies each run with kurbo, and keeps a run as it
was when its fit strays more than twice the accuracy from it. The Pencil
and vector.simplify use it.
2026-11-09 06:15:33 +01:00
Trevor BrownandClaude Fable 5.1 4118be890c Ellipse: the four-cubic contour is closed, and the band test allows apex antialiasing (#2080)
The band test compared row 10, the ellipse top, where the cubic now ends exactly at its level extreme; 8 pixels antialias slightly differently between a short band and the whole view. The row mean limit now grows by 0.05 per such pixel; whole-row artifacts still fail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-07 12:42:44 -05:00
Trevor BrownandClaude Fable 5.1 b33da8a7b0 Ellipse: an unsliced ellipse edits as four anchor points, not six (#2080)
A whole ellipse and each ring contour are built as four cubics through the extremes instead of a tolerance-subdivided arc. Sliced ellipses are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-07 11:52:52 -05:00
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