One of the core deliverables for me was a great xterm experience. If you code on the Mac you use a lot of iTerm2 , which I consider the gold standard for appearance of terminal text. It has a million settings, several of which adjust how text renders.

I shared this with Claude and we used iTerm2 as our guidepost for how we wanted xterm to display on the Mac. We went through a few days of trying to get Mac fonts to fit inside predefined text glyph boxes but the text often looked too bold or too spaced out. It was kind of a mess.

Claude and I had a lengthy discussion about this and out of that discussion came the realization we were kind of doing it backwards. Once we started getting the box size from the Mac font itself, it all came together.

claude, replay the entire font fiasco from a few weeks ago and explain how we fixed the problem.

Yeah, that one took us a while to land. Let me walk through it day by day, because the wrong answer and the right answer look almost identical from the outside, and the difference is just which direction the metrics flow.

The thing xterm cares about is exactly one font-shaped value: the cell size. It allocates its window based on cellWidth × cols by cellHeight × rows. Every glyph it draws goes at a fixed (col × cellWidth, row × cellHeight) offset. When xterm -fn 7x14 asks the server for a font with a 7×14 cell, xterm expects every glyph to fit cleanly in that cell. If the server tells xterm “your cell is 7×14” but renders glyphs that overflow it, you get descenders bleeding into the next row, underlines landing in the wrong place, and a terminal that visually doesn’t add up. Whatever cell we report has to match the cell we actually draw.

Day 3 was the first attempt. I had an XLFD parser, a font resolver, and a draft of ImageText8 working. The naive approach: take xterm’s requested cell (say 7×14), divide it by Monaco’s natural advance ratio and line-height ratio, and instantiate Monaco at whatever pointSize fits. So Monaco at about 11.4 points to fit a 7×14 cell. The cell math worked. xterm got the metrics it asked for. We thought we were done.

Day 4 was when the trouble started showing up. The text was technically correct but read as “too bold,” with stem asymmetries that made the rendering look subtly off. I corrected Monaco’s line-height ratio from 1.07 to 1.2 thinking that was the issue, but the basic problem stayed. The reason: Core Text’s hinter does its best work at integer pointSize. Monaco at exactly 10pt or 11pt or 12pt is hand-tuned by Apple to render cleanly at every device pixel. Monaco at 11.43pt is not. Core Text rasterizes the outline at fractional sizes by interpolating, and the interpolation produces stem-width inconsistencies that read as weight noise. We were instantiating Monaco at whatever fractional pointSize the cell math demanded, and Core Text was rasterizing it as well as it could, but “as well as it could” wasn’t iTerm2-grade.

Day 5 was the flip you remember. Instead of fitting Monaco to xterm’s cell, we picked Monaco’s pointSize first and reported Monaco’s actual cell back to xterm. The procedure:

  1. Look at the cell xterm asked for (say 7×14).
  2. Compute the integer pointSize closest to fitting that cell.
  3. Instantiate Monaco at that integer pointSize.
  4. Ask Core Text for Monaco’s actual advance, ascent, descent, and lineHeight at that pointSize.
  5. Report Monaco’s actual cell back to xterm in the QueryFont reply.

Step 5 is the inversion. The XLFD becomes a hint, not a contract. xterm uses Monaco’s metrics for layout, and the metrics it gets back are the metrics that get rendered. There’s no possibility of a mismatch because there’s only one source of truth: Monaco at the chosen integer pointSize.

This is what “reported metrics equal rendered metrics by construction” means. We’re not picking the font to fit the cell. We’re picking the cell to fit the font.

A few practical consequences. Several xterm aliases collapse onto the same pointSize because Monaco’s aspect ratio at any integer pointSize is fixed at about 1:2.2. Different requested aspect ratios all map to the closest Monaco-natural cell:

AliasReports back asMonaco at
5x73×75pt
6x104×97pt
fixed / 6x13 / 7x13 / 7x14 / 8x136×1310pt
7x15 / 9x157×1511pt
8x167×1612pt
10x209×2015pt
12x2411×2418pt

xterm -fn 7x14 -geometry 80x24 produces a slightly smaller window than the named dimensions suggest (480×312 logical pixels instead of 560×336). The user gets Monaco rendered crisply at 10pt, which is what they actually wanted.

The same invariant generalized later. Day 11 applied it to QueryTextExtents for proportional fonts, which fixed the Motif menu-title spacing on quickplot. Day 14 hardened it into the MOTIF_TEXT_QUALITY contract: every glyph carries a per-character characterWidth value, and both the reported width and the rendered advance come from the same Core Text source. Same principle, broader scope.

The bar for the project was that an xterm rendered on macXserver had to sit comfortably next to an iTerm2 window. Otherwise the project had failed. Day 5 was the day that bar got met. Every text-rendering decision in macXserver since then has been a variation on the same theme: pick what looks right at integer pointSize, and report what you’re actually going to render.

claude, did xterm’s historic use of bitmap fonts lead us initially down the wrong path?

Yes, absolutely. xterm was designed when bitmap fonts were the only option. The XLFD naming convention encodes the bitmap-era assumption directly: a font name like 7x14 literally specifies “a font with 7-pixel-wide, 14-pixel-tall cells.” In the bitmap world, the cell size defines the font. They’re inseparable. There’s no choice to make about pointSize because there is no pointSize. You have a .pcf file with fixed-pixel glyphs and that’s that.

That convention got baked into the X protocol semantics. When xterm -fn 7x14 asks the server for a font, classic X servers respond by looking up 7x14.pcf in their catalog and returning the cell metrics from that bitmap file. The spec language reinforces it: the pixel-size field, the cell-width naming, the rendering assumptions. Everything points to “deliver this exact cell.”

So when I approached the problem from the X protocol spec, the natural interpretation was: xterm wants a 7×14 cell, my job is to deliver a 7×14 cell. That’s what every X server before us did. That’s what the spec asks for.

iTerm2 never had this problem because iTerm2 doesn’t speak the X protocol. It picks a font, instantiates it at an integer pointSize, and the cell is whatever Monaco gives you. iTerm2 had the freedom to invert the relationship because it wasn’t inheriting 30 years of bitmap-era semantics.

So yes, the bitmap history led me directly to the wrong framing. This is the same bias I described in lift, don’t intellectualize from another angle: when a spec encodes assumptions that no longer apply (bitmap fonts, in this case), reading the spec literally is exactly the wrong move. The XLFD convention is correct for bitmap fonts. It’s wrong for scalable fonts. The protocol just doesn’t acknowledge the difference.

claude, is that what XQuartz does as well?

Yes. XQuartz takes the bitmap-catalog path for core X protocol fonts. If you xlsfonts on XQuartz you’ll see all the classic XLFDs (7x14, 9x15, fixed, etc.) and they’re all backed by .pcf bitmap files shipped under /opt/X11/share/fonts/misc/. xterm asks for 7x14, XQuartz looks up 7x14.pcf, glyphs come out at exactly 7×14 device pixels. Same approach the X.org server uses on Linux, same approach Sun’s OpenWindows used, same approach every X server has used for 30+ years.

XQuartz also supports Xft, the modern X font extension that bypasses the core protocol. With Xft, the client renders fonts itself using FreeType, and the server is just a pixel store. That gives you scalable fonts, but only for clients compiled with Xft support, and only when the user passes -fa (font-antialiased) instead of -fn (font-name). Default xterm -fn 7x14 doesn’t take that path.

The macXserver approach is different from both. We don’t ship a bitmap catalog at all. We don’t depend on the client supporting Xft. Every core protocol font request resolves to a Mac font at integer pointSize, server-side. xterm -fn 7x14 works through the standard core protocol path that every xterm has supported since 1985, but the cell it gets back is Monaco’s natural 6×13 at 10pt rather than a literal 7×14 bitmap.

So XQuartz is bitmap-faithful to the spec. macXserver maps scalable Mac fonts through the same protocol surface. Both are valid takes on the same constraint; they just look different when you put them side by side.