Fix post-taffy-bump layouting issues (#61107)

Follow-up to https://github.com/zed-industries/zed/pull/60721

Before:
<img width="564" height="470" alt="before"
src="https://github.com/user-attachments/assets/d825464d-f8d9-4fa1-bee3-42b5f615d4ba"
/>

<img width="745" height="221" alt="image"
src="https://github.com/user-attachments/assets/18139bec-6778-491a-9aa5-0112bd121723"
/>


After:
<img width="576" height="472" alt="after"
src="https://github.com/user-attachments/assets/4c3c37cf-12c4-421e-98e9-cc6e40aa099d"
/>

<img width="812" height="275" alt="image"
src="https://github.com/user-attachments/assets/407e06b4-101f-4984-8d5b-4e33895b5ae9"
/>


### Bug 1 — constraint-blind text layout cache (the collapse)

`TextLayout`'s measure closure is stateful (each call overwrites the
shared element state used for painting), and its cache check served
cached sizes to unconstrained probes regardless of the constraints they
were computed under:

1. `uniform_list::measure_item` lays an item out at `(MinContent,
MinContent)`; the row's `min_w_0` lets it shrink to ~0, so labels get
truncated at a tiny width — and that tiny size lands in the element
state.
2. The real layout probes the label's flex base size with
`available_space.width = MaxContent` (taffy maps Definite → MaxContent).
Truncated labels are `whitespace_nowrap`, so both `wrap_width` and
`truncate_width` were `None` → the cache check passed → the poisoned
tiny size became the flex basis → labels rendered at ~5 chars.

**Fix**: record `truncate_width` in `TextLayoutInner` and never serve a
cached layout that was computed *with* truncation to an unconstrained
probe; the honest intrinsic size is recomputed instead, and the final
`PerformLayout` call re-truncates against the real resolved width.

### Bug 2 — truncation width math disagrees with shaping (the ~2-char
loss)

After fix 1, rows got their full width, but exact-fit strings like
`Cargo.toml` still lost ~2 chars:

- Sizing measures via `shape_text` (real shaping with kerning); the
element gets exactly `ceil(shaped_width)`.
- The truncation decision (`LineWrapper::should_truncate_line_middle`
etc.) sums **per-character advances** — no kerning — with zero
tolerance, overestimating width for some glyph sequences. Text sitting
in a box of exactly its own measured width got truncated, losing ~2
chars to fit the `…`. String-dependent (kerning pairs), hence
`Cargo.toml` broke while `Cargo.lock` didn't.
- Previously masked because taffy 0.10 usually skipped the final measure
invocation, so the truncation path rarely ran with an exact-fit width.

**Fix**: before truncating (nowrap case, `wrap_width.is_none()`), shape
the untruncated text and skip truncation if the *shaped* width fits —
matching CSS `text-overflow`, which only activates on actual overflow.
Cheap: the shaping result is a `line_layout_cache` hit from the earlier
untruncated sizing probe.

### Bug 3 — `MinContent` used instead of `MaxContent` that caused over
truncation of certain labels

Release Notes:

- N/A
b05f40c554Kirill Bulatov committed on 7/16/2026, 5:23:49 PM· committed by GitHubparenta0bb97c
3 files changedLine totals unavailable