Main's file dialogs answer asynchronously now (they no longer re-enter the
event loop on macOS); the menu item takes the path in a callback, and the test
draws a frame to let the dialog answer.
468 of the 588 command and menu rows had the command id as their text
("align.bottom" = "align.bottom"), which the app would have shown as is.
They are left out, so English shows until they are translated. Swedish
isn't in the complete list (that would make every new UI string need a
Swedish translation in the same change); the docs say what it covers.
A text edit holds an interaction too, so treating any open interaction as a
drag dropped the colours clicked while editing text. Recent colours dedupe by
8-bit value: the colour picked and the one the document stores differ by a
rounding fraction.
A click or Tab into a one-line field selects all of its text, so typing
replaces the value, as in Figma: hex and colour fields, inline fields
(a fill's hex, variable values, renames), names, the font size field,
search boxes and dialog fields (widgets::select_all_on_focus). A drag
from the press still selects only what it covers; multi-line fields
keep the caret where clicked.
The first click into an inline field (a fill's hex) now takes the
keyboard: egui dropped the focus of the editor created by that click,
so it took a second click.
Text in the default Inter (or any Latin font) drew the missing-glyph box for every Hangul
syllable on macOS and Windows: no Korean family was on the fallback list, so the Korean
fonts those systems ship were never tried, and there is no default-font setting to work
around it. Apple SD Gothic Neo (macOS), Malgun Gothic (Windows) and Noto Sans CJK KR /
Noto Sans KR (Linux) now come after the Chinese and Japanese entries, so Han characters
resolve as before.
Fallback faces also follow the run's style: each fallback family gives its face nearest the
run's style instead of always its Regular, so Hangul (or kana) in a bold run comes out bold.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015MAPjgJo17KasfbzMTbV65
Where the 512 px cap held the light short of half a level, it dropped to 0
in one pixel: a ring 512 px inside a deep pane (46 levels at depth 300,
splay 1, 200%). The falloff now reaches 0 at the reach. Where the cap
doesn't bite this moves the light by at most half a level.
Cut tests now also cover rounded corners and a look under the cap.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every hex field (fills, strokes, text ranges, effects, layout grids,
colour variables, page and prototype backgrounds, the colour picker)
now takes any of the 148 CSS named colours. Case, spaces, hyphens and
underscores are ignored; hex wins where both could match; names are
opaque and keep the colour's opacity. Color::parse_css (the picker's
CSS field and command colour params) takes the full list too.
Require resolved font entries to be regular files before indexing them. Preserve normal font symlinks and cover named pipes in a bounded child-process regression.
Assisted-by: OpenAI Codex (GPT-6)
Signed-off-by: IanHollow <72767437+IanHollow@users.noreply.github.com>
Where nothing bends (past `depth`, or with no refraction) the three
colour channels sample the backdrop at the same point: one sample
instead of three. The rim light's facing and powers are worked out only
where the light reaches. Same bytes: an ignored `glass_digests` test
prints digests of 30 renders (5 looks, square and rounded, 3 scales),
identical before and after this change (and to main).
Refs #256
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The glass light falls off with the distance to the edge, read past
`depth` (up to ~3 × depth at full splay), but the coverage window around
a cut layer was only `depth + 2` wide. With frost and refraction at 0
the backdrop margin is 0 too, so a band or canvas patch edge running
through the pane changed the light near it: up to 12 levels between a
banded and a whole render.
The window now covers the light's reach (where it falls under half a
level, clamped at 0 and capped at 512 px) plus the span the normals are
smoothed over, and past that reach the light is 0 instead of whatever
the window happened to hold.
Tests: a cut 50–80 px inside the pane equals the whole render byte for
byte (fails on main by 12 levels); light_reach edge cases. Adds an
ignored release timing test (glass_bench_tests).
Refs #256
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
W and H ignored scrubs. They now scale live in one undo step. The factor
field applies on release, because it is relative to 1.0 on every frame.
Refs #256
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Delays, scroll offsets, overlay offsets and the overlay background alpha
were set on every frame of a scrub, an undo step each. They now set once,
when let go, like the custom size field.
Refs #256
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The RGB/HSL/HSB fields committed every frame of a scrub, so one drag left
about ten undo steps, and the alpha field ignored scrubs. Both now edit
live and commit when let go.
Refs #256
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Restore the original cell spacing and check the table geometry across text sizes instead of requiring every font to fit without scrolling.
Assisted-by: OpenAI Codex (GPT-6)
Signed-off-by: IanHollow <72767437+IanHollow@users.noreply.github.com>
The browser-worker test assumed a fixed 2400x2400 glass scene renders
in at least 12 ms; a faster machine or renderer (the glass speedups)
would make it quick and the test fail. The scene now gets more and
more blurred rectangles until renders from scratch of the views the
test uses take three times the threshold.
Refs #295
A hyperlink longer than 200 characters came back as a different 200-character
URL -- one that still looks like a working link -- and the import reported
nothing. It applied to a text layer's base style and to a character style
override alike.
The destination went through `clip_str`, which exists so that names and labels
from a file stay readable when they are quoted in a warning. Every other caller
is a name, a description, a style id or a layer type; a hyperlink is data, and
clipping it silently rewrote it. Two things say so: the FIG importer already
keeps the URL whole, so the two importers disagreed, and `rest::props` bounds
numbers and list lengths but no string beyond that label helper -- the text
content itself is not clipped either.
The reporter's integration test is included, with its assertions unchanged. Its
helper is restructured to return what it found rather than unwrap: the crate
denies `unwrap_used` and `panic`, and `clippy.toml` allows them only inside a
`#[test]` function, so the original shape failed the gate before it ran. Its
failure message now reports the input and output lengths.