Tilo Sans 1.002: ship the distinct I and l and the slashed zero #1

Merged
qwolff merged 6 commits from il-r6 into main 2026-10-05 01:28:35 +00:00
Owner

Ships ss13, cv01, cv02 and zero in the default build (HELD_BACK keeps only Cyrillic) and bumps the fonts to 1.002.

Since review:

  • I/l at 12 px. The tailed l keeps 126 units from a following stem or figure, so l1 no longer greys into a U, and 70 from other letters, so the condensed bold no longer opens up around its l's. The condensed bold tail rises into a second pixel row, so lL stays apart from LL.
  • Figures and bars. Figures keep 80 units on both sides of the serif I and the tailed l (4l, 7l, I4). Bars level with a serif keep 126 (7I, TI).
  • The zero. The condensed bold zero keeps its weight (196-unit counter, 134-unit sides). Its slash is long enough not to read as a tick (40 units clear of the counter, 75° in the narrow counter).

Checks: build.py, il_forms.py --check, il_kern.py --check (settled), pairs.py (0 collisions, exact figure and tail floors), components.py, shaping_tests.py (default/ shapes the features exactly as full/) and verify_upstream.py (all 501 upstream outlines and advances unchanged; the 42 intended shaping differences). The default build reproduces byte for byte with SOURCE_DATE_EPOCH.

Review: proofs/final/il-review/, plus 4x renders through Tilo's own text stack (the app windows, a 12–17 px specimen, and a 16x outline comparison).

🤖 Generated with Claude Code

Ships `ss13`, `cv01`, `cv02` and `zero` in the default build (`HELD_BACK` keeps only Cyrillic) and bumps the fonts to 1.002. Since review: - **I/l at 12 px.** The tailed l keeps 126 units from a following stem or figure, so `l1` no longer greys into a U, and 70 from other letters, so the condensed bold no longer opens up around its l's. The condensed bold tail rises into a second pixel row, so `lL` stays apart from `LL`. - **Figures and bars.** Figures keep 80 units on both sides of the serif I and the tailed l (`4l`, `7l`, `I4`). Bars level with a serif keep 126 (`7I`, `TI`). - **The zero.** The condensed bold zero keeps its weight (196-unit counter, 134-unit sides). Its slash is long enough not to read as a tick (40 units clear of the counter, 75° in the narrow counter). Checks: `build.py`, `il_forms.py --check`, `il_kern.py --check` (settled), `pairs.py` (0 collisions, exact figure and tail floors), `components.py`, `shaping_tests.py` (`default/` shapes the features exactly as `full/`) and `verify_upstream.py` (all 501 upstream outlines and advances unchanged; the 42 intended shaping differences). The default build reproduces byte for byte with `SOURCE_DATE_EPOCH`. Review: `proofs/final/il-review/`, plus 4x renders through Tilo's own text stack (the app windows, a 12–17 px specimen, and a 16x outline comparison). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The forms are now drawn by scripts/il_forms.py in all eight masters from
each master's own I, l, t and 0 and a table of design values, so they stay
point-compatible and can be redrawn rather than hand-edited.

- l.ss13: a short tail on an arc that turns up and ends square to the
  stroke, with a round outer corner, about a third of n's width, so it no
  longer reads as L's flat foot or t's tail at 12-14 px.
- ł keeps its plain form under ss13 and cv02 (lslash.ss13 removed): a tail
  under the bar is t's silhouette.
- I.ss13: shorter serifs and 63-unit sidebearings, so II and III keep 126
  units (1.5 px at 12 px) between their serifs and I1 stays two shapes.
- zero.zero: a slash inside the ring, heavier in the condensed bold so the
  zero stands apart from O.
- il_kern.py: the serif I and tailed l keep 40 units from anything in any
  direction, the tail's end 90 from a following letter or figure, the
  plain distance next to l i j and their accents; distances are solved
  with a margin so the exact outlines keep them; lcaron.ss13 is measured
  like the other tailed l's.
- pairs.py measures the serif I and tailed l against figures, accents, ¿ ¡
  and each other exactly on the outlines; shaping_tests.py checks that ł
  keeps its plain form; il_sheet.py proofs lL, LlL, II, III, I4, Ø ø θ and
  real identifiers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/il_sheet.py --review writes proofs/final/il-review/: the identifiers
and confusables in Regular, Bold and Condensed Bold, upright and italic, at
12, 13 and 14 px, the default forms beside ss13 + zero, light and dark, at
1x and 2x and the 1x page enlarged.

Reviewed at 1x, ł and II/III pass; the areas stay held back because four
cases still fail on the pixels while passing on the outlines: l1 fuses into
a U in Bold at 13 px (the tail keeps only the 90-unit minimum), the tailed
l renders as a short L in the condensed bold, I4 fuses in the condensed
bold (40-45 units), and the condensed bold zero's slash fills its counter
so 0, θ, Θ and Ø look alike. The README lists each with what it needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tailed l keeps 126 units (a pixel and a half at 12 px) after its tail
before a figure, | ¦ ! ¡ or any letter but a round, through a larger right
sidebearing and kerning, so «l1» no longer greys into a U at 13 px in Bold.
Beside a figure the masters keep 14 more, so the instances between the
condensed masters keep 126 as well.

In Condensed Bold the tail's end rises at 65 degrees to 170 units, so the
upturn spans two pixel rows at 12 px and «lL» no longer reads «LL»; the
tail is a little shorter there (138 units past the stem) to keep the wider
advance in proportion.

The serif I and the tailed l keep 80 units from a figure in any direction
(40 before), so «I4» and «4I» stay two shapes in the condensed bold;
lcaron.ss13's caron keeps 80 from a figure too. pairs.py now enforces the
figure floor (80 at the masters, 76 between them) and the tail's 126 (120
between them) on the exact outlines.

The slashed zero in the condensed and heavy masters gets a shorter slash
that stops short of the counter at both ends; the condensed bold zero has
thinner sides and a slightly wider outside, so its counter is 236 units
instead of 152 and 0, θ, Θ and Ø stay apart at 12-14 px. Regular keeps its
slash ending in the ring.

The review sheet in proofs/final/il-review/ is re-rendered for sign-off;
the features stay held back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The distinct forms leave HELD_BACK, so fonts/default/ carries ss13, cv01,
cv02 and zero; shaping_tests.py checks they shape there exactly as in
fonts/full/ (and still do nothing while an area is held back).

Spacing in the condensed bold no longer opens around the tailed l: the
tail keeps 126 units only from a following figure, | ¦ ! ¡ or letter whose
left side is a stem beside it, 70 from every other letter, and next to a
round the stem keeps a sixth of the tail's extra width instead of a third.
The condensed bold tail is a little lighter (88) and rises at 72° to 165,
so the upturn still fills a second pixel row at 12 px.

A figure before a tailed l keeps 80 units like a figure beside the serif I
(4l and 7l were Instrument's 54 in the condensed bold and fused there);
il_kern.py writes these glyph pairs and pairs.py checks them. The serif I
keeps 126 units, as from another serif I, from a bar or arm level with its
serifs (7I, TI, IT, I7 read as one bar at 87 in the condensed bold italic),
found by comparing the partner's reach at the serif with the middle of the
stem.

The condensed bold zero keeps most of its weight: a 196-unit counter with
134-unit sides, against 236 and 114, which looked faint beside the other
figures at 12 px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Where the slash stops short of the counter (Bold, the condensed masters and
their italics) it now stops 40 units from it along its length, 24-36 beside
it, instead of 70-80 and 26-40. With the condensed bold's narrower counter
the old clearance left a short tick in the middle of the zero, which at
large sizes read as a dotted zero; at 12 px the slash still leaves white on
both sides, so the counter does not fill grey.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the condensed bold's 196-unit counter the side clearance, not the
clearance at the tips, set the slash's length: at 66° it stood 214 units
tall in a 520-unit counter and still read as a tick. At 75° it reaches 278
units, about half the counter as in Bold, with the same clearances; at
12 px the counter keeps white beside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
qwolff merged commit 07a4c839d7 into main 2026-10-05 01:28:35 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
tilo/tilo-sans!1
No description provided.