Fix #442: alike circular corners on rectangles that aren't square

Live rectangles drew elliptical corners after an uneven scale in v0.4.0;
inconsistent on a rectangle that isn't square:

- doc: LiveShape::fold_scale moves an uneven scale left in `xf` (files
  saved before #291) into the size and radii; `transform` uses it, and
  `folded()`/`corner_style` give Live Corners document units.
- engine: object.setLiveShape folds that scale first, so setting a radius
  or kind (fields, dialog, widgets, MCP) gives circular corners on such
  shapes instead of keeping the ellipses.
- geom: max_corner_radius/fitted_corner_radius are the one limit every
  corner shares (half the shorter side).
- tools: corner widgets sit at the centres of the corners as drawn (a
  radius past the limit put them off the arc, further in along the long
  side), drag in document units on stretched shapes, and outline the
  edited corners in red at the limit, as the reference app does.
- svg: CSS export writes the drawn radii (CSS would draw a radius past the
  limit when its neighbours leave room).
- docs: mcp.md Live Corners, ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-08 14:34:37 +07:00
co-authored by Claude Opus 5.5
parent 7c7ce7f4fb
commit 44c7e64e1b
9 changed files with 266 additions and 48 deletions
+6 -3
View File
@@ -1088,9 +1088,12 @@ size. The journal entry of a scaling command records the `strokes` and `corners`
2 bottom-right, 3 bottom-left), else to the corners holding a Direct-Selected anchor (`select.anchors`), else to all
four. Each corner keeps its own radius and kind (the shape's `live` in queries has `radii` and, when a corner isn't
round, `kinds`); a corner with no radius is one anchor, a cut one two, and Direct-Selected corners stay selected as
that changes. With the Selection or Direct Selection tool, dragging a corner widget rounds the corners whose widgets
show (all four, or the Direct-Selected ones), Alt-clicking one cycles their kind and double-clicking one opens Corners
(`ui.corners {id?, corners?}`, dialog `corners`: `kind`, `radius`; OK runs `object.setLiveShape`).
that changes. Every corner is a circular arc, whatever the rectangle's proportions: a radius past half the shorter
side draws at half of it (the same limit for every corner), and a rectangle from a file that kept an uneven scale in its
transform (elliptical corners) gets circular ones in document units when its corners are next set. With the Selection or
Direct Selection tool, dragging a corner widget rounds the corners whose widgets show (all four, or the Direct-Selected
ones), outlining them in red once they reach that limit; Alt-clicking one cycles their kind and double-clicking one
opens Corners (`ui.corners {id?, corners?}`, dialog `corners`: `kind`, `radius`; OK runs `object.setLiveShape`).
```json
{"name":"run_command","arguments":{"command":"object.setLiveShape","params":{"id":12,"corners":[1],"radius":16}}}