I need a word.

Imagine that we have a Tinderbox document. It might have lots of rules and agents. It’s got lots of notes of various kinds. We take a snapshot of the document...right NOW! We’ll call that snapshot the document’s “state”.

Now, we make some changes — adding notes, perhaps, or editing some old notes. And then, we accurately undo each change we’ve made, one by one, until we’re back at the starting point.

Now, is that document’s state changed, or is it not changed? I need a word to describe Tinderbox documents where the state is unchanged.

Want an example? Suppose I have an agent:

Query: $Name=='Communist'
Action: $Color(agent)='red'

The agent is black when we start. If I create a note named “Communist”, then the agent will turn red. If I then undo my action, deleting “Communist”, the agent will still be red. The agent will be red if there is now, or there has ever been, a Communist.

If I remember Peter Thompson’s seminars on Thermodynamics correctly — which I might not — the word for a non-reversible Tinderbox like this would be ergodic. But Espen Aarseth used “ergodic text” to mean something entirely different , and that usage is now established. (I told him at the time it was a mistake, that someone might need the original meaning. I never thought that I would need it. Oh well.)

We could use “reversible,” but that will make people think of Spring outerwear, won’t it?

We could aim for the Latinate equivalent of the Greek “ergodic”. But “laborious Tinderbox” would be wrong, “operatic Tinderbox” euphonious but misleading, “fabriffic Tinderbox” looks absurd even though it’s got a terrific ffi ligature for font freaks. Something might be made of exerceo as an exercise for the reader. But I’m not feeling it.

There’s got to be a better word. Email me.

I was making a meatloaf Sunday night, mostly because Savenor’s had some very nice ground meat. I like meatloaf. I figured I’d make the pate en terrine from Ruhlman’s Twenty and get on with work while it cooked.

Then Linda delivered the bad news: we were out of ketchup. Was I planning to make the ketchup from Ruhlman’s book, too?

No, I was not planning on that — not least because the recipe calls for three hours of simmering and it was already past seven. But now I wanted ketchup for the meatloaf! So I made Ruhlman’s chipotle ketchup and just simmered it for whatever time I had — maybe 45 minutes. And it was great.

This is a good general lesson about cooking. Lots of things are better if you do them right, but they can turn out pretty well even if you have to cut corners.

I spent about a day this week polishing a detail of Tinderbox Six. I’d like to walk you through some of the design because it’s interesting and accessible, and because I think it demonstrates why our expectations of software are leading us into such a terrible mess.

Under the hood, this feature is called Tansey Tabs, named for the distinguished university administrator who first suggested it. Tinderbox encourages you to open lots of windows on different facets of your document. You might have a map of the section you’re working on, an outline of references and sources, another outline of tasks remaining to be done, perhaps a treemap overview of everything. This gives you lots of flexibility and lets you tailor your workspace. But using lots of windows can sometimes be tricky, and increasingly it’s not something people discover for themselves; why not use tabs within one window to provide quick and easy access to as many views as you need?

How Software Is Built Today

This isn’t off the shelf, but that’s OK — we’ll just build it, it’s not rocket science. And it’s a feature that’s nice, not one that’s essential. Lot’s of people won’t use these tabs.

So, what do we need to think about when adding a bar of tabs like this?

  • The whole point is to have a view state that summarizes what you’re looking at and how it’s presented. You want to switch between view states. So we need a new object that encapsulates the View State, methods for updating the view state when the view changes or you switch tabs, methods for allocating memory for the view state and cleaning up afterward.
  • You need a bar in which the tabs live. That bar needs to have something drawn on it, which means choosing a suitable gradient or texture.
  • The tab needs a suitable shape. That shape is tricky enough to draw that we define an auxiliary object to frame and draw it.
  • Whoops! It gets drawn upside down! Slap head, fix that.
  • We need a way to add new tabs. Make a subtle button, attached to the right edge of the tab bar. Make sure that the tabs are arranged so the button won’t be covered by tabs, even if there are a ridiculous number of tabs.
  • The tab needs a label. That also means choosing a font, color, and type size.
  • When a tab is clicked, we need some feedback. So, while the mouse is down, we’ll change its color slightly and change the label color as well.
  • The currently-selected tab needs to be distinguished. It has a lighter color. And, because it’s notionally in front of the other tabs, perhaps it needs a slightly more pronounced shadow.
  • We need a way to delete tabs we no longer want. It’s easy enough to add a close button to each tab, but that adds a lot of visual noise. So, we’ll only show the close button when the mouse is over the tab.
  • There’s always a current tab, the place where the view you’re looking at puts its view state. So you can only delete other tabs, not the current tab. This requires a little extra logic.
  • Tabs needs to be saved with the document. That means we need to be able to encode a ViewState as XML, and we need to be able to read that XML and create a ViewState from it next year. And this needs to be done right, because if you make a mistake in the XML, you’re going to be writing code to work around it next month — and you’ll still be working around that mistake in ten years.
How Software Is Built Today
  • As soon as you save a file and start to actually use the tabs, you realize that you want to reorganize them. Everyone will want to reorganize them. So, allow the user to drag a tab inside the tab bar to change the order of tabs.
  • If the user drags tab A over tab B, the tabs swap places in the bar. This might look nicer with an animation, so try one. It does look nicer. Now, when tab B moves to its new place, does it slow down when it gets close, like a car applying the brakes? Or does it speed up, like a magnetic clasp? How fast should it move?
  • If the user drags tab A all the way to the right, it’s over the place tab 7 would be if there were a tab 7. But there isn’t a tab 7, so we crash. There’s no tab −1 either. Fix those.
  • If the user clicks too forcefully, the tab thinks it’s being dragged, not clicked. So, treat tiny drags as if they were clicks.
  • That’s functionally good, but now clicking the tab makes the tab jiggle a little bit. It doesn’t feel solid. At this point, I’m getting to hate tabs. But let’s add logic so the tab doesn’t move until you’ve clearly started to drag it, and then “tears off” to catch up.
  • Writing “Outline” or “Map” on each tab makes the kind of view clear, but it takes up a lot of space. Let’s add an icon or thumbnail that shows a little bit of what the view looks like. The obvious approach is to draw a tiny picture of the view. Getting this to look good seems to require more vertical space than I’m willing to spend on this feature.
  • It turns out that the thumbnails look pretty terrible. Instead, we’ll hand-draw the icon. We use the color scheme from the selected view as a hint. We could go further and draw a highly abstract picture of the view, optimized for a tiny space. Put that on the ToDo list.
  • Today’s computers have several processors, so we can ask another processor to help out when we need to set up a new view. And when the view changes, we can animate the transition. But with lots of tabs, we might click tabs so quickly that we start setting up a new view, begin a lot of animations, and then switch tabs again before those animations are done. Yikes! And what if you asked for a wakeup call when the animation was finished? And then the user closed that tab? Now, you’re gone and there’s no one to answer the call. Crash!
  • And we need some additional unit tests to ensure that all of this continues to work as the ViewState object and the views that use it change.

This is a hell of a lot of design and implementation for a small feature. The old answer was “reusability,” but that’s no good; we need more than NSSegmentedControl can give us.

This kind of detailing gets lots of attention in the tech press, because it’s thought to be a secret of Apple’s success and talking about (or against) Apple is always good for circulation.

This is a hell of a lot of design and implementation for $0.99. But that’s increasingly what people expect to pay for software. OK: maybe $19.95 for something really terrific. But can you sell an extra 100 copies of the program because it’s got draggable tabs? If you can’t, don’t you have better things to do with your time?

This is a hell of a lot of design and implementation for an auxiliary feature. Tinderbox isn’t about tabs. Tinderbox is a tool for notes, for visualizing, analyzing, and sharing. Tabs are just a nice things that some people will use and others won’t. And some people will give you 1-star reviews because they don’t like the shadows, or the typography looks bad in Sanskrit. There’s always something you forget.

But it can be done. One day to implement the tab bar. One day for dragging and saving tabs. OK: a pretty good day both times, but just a day. And if I can just string about 270 of those days together, we’ll be ready for beta.

Jan 13 27 2013

Dog Food

I just shifted my programming notebook to open in Tinderbox Six. So, now the notebook and the weblog are both using the new code. We’re making progress.

The big push this week has been performance. Load time for this document has been cut from 32sec to 3.5sec. Lots of work tracking down memory leaks, too.

They do not preach that their God will rouse them a little before the nuts work loose.

They do not teach that His Pity allows them to drop their job when they dam'-well choose.

As in the thronged and the lighted ways, so in the dark and the desert they stand,

Wary and watchful all their days that their brethren's day may be long in the land.

Jan 13 26 2013

The Aviator

by Gareth Renowden

Truffle farmer and magazine expert Gareth Renowden ventures into SF with this lively romp through a ruined earth in the wake of global warming. Global cataclysm doesn’t phase Lemmy, his intrepid Airshipman, nor his gallant, artificially intelligent airship, from making their corporate rounds. The opening has buckets of exposition — not unexpectedly, perhaps, given Renowden’s expertise in eco-journalism — but there’s plenty of fun.

The book is structured as a series of encounters with isolated pockets of survivors. This familiar approach can be compelling, but it helps to give the protagonist more narrative direction than laid back Lemmy can consistently muster. Still, this feels like early late-period Heinlein, and that’s not a bad thing.

It bothers me that so much of the press (and Wikipedia) coverage of Aaron Swartz assumes that he planned to redistribute the JSTOR articles he downloaded. That’s possible, but it’s probably wrong.

Aaron studied large collections of texts. His landmark Wikipedia research asked who really writes Wikipedia by examining the provenance of thousands of articles. He showed, contrary to what nearly everyone expected, that most of the information came from a wide range of specialists who edit Wikipedia infrequently, while a small core of very visible editors each contribute thousands and thousands of small, technical edits. He published that work himself, but it would have waltzed into ACM Hypertext or Web Science. Later, he did a similar study of legal citations for the Stanford Law Review.

This was one of Aaron’s core strengths. Swartz had a good intuitive sense of what studies would be practical on modern computers. I’ve done some work on text collections myself, but while I know it’s possible to study a million documents, all my reflexes are tuned to smaller studies. So, “Link Apprentice” used the Federalist Papers and Shakespeare, and my studies of “Patterns of Hypertext” and “Criticism” have about a hundred references. I don’t reach for the millions first; Aaron could.

There is nothing wrong with this kind of research. It’s possible that it technically violates JSTOR’s terms of service, but it’s always been part of what we mean by “using the library.” If I want to study bookbinding by looking at a million books in Widener and noting whether they’re red or blue or green, my GSAS doctorate says I have every right to do so. If I’m making too much noise or get in Professor Higginbotham’s way, then we can discuss ways to make less noise or visit the fourth floor when Higginbotham is in a better mood.

This doesn’t mean that Swartz did nothing wrong. Students do all sorts of things that are wrong. In college, we used to break into the swimming pool to go skinny dipping on Spring evenings; this would have gotten Jean Valjean in a pickle and broke any number of rules and laws and it wasn’t really safe (though we had lifeguards), but it was fun. I knew people who visited other forbidden places: Clothier Tower (off which a sorority reject threw herself in the apocryphal past), the dome of Parrish Hall, the underground network of steam tunnels.

It’s not impossible that Swartz planned to share the JSTOR downloads somehow. But I know of no evidence for that, and there’s plenty of reason to think we was working on a new large-scale text study.

Tinderbox 1 was designed for a machine of nearly indescribable antiquity: a 600 mHz PowerPC with one core, no GPU, no multitasking, and no screen buffer. And Tinderbox assumes that you’ll have lots of windows viewing the same document. As a result, Tinderbox has an elaborate system for notifying each window about each change in the document, letting it figure out how much work it needs to do.

We’re in a new era. Even low-end laptops have multiple cores and dedicated graphics processors. Everything’s double-buffered, and most stuff is composited from secondary buffers. We have lots more memory.

I sometimes think that all this rigamarole is a waste nowadays. Perhaps we should just update everything periodically, and skip trying to minimize the update work. Sure, some CPU will be wasted, but we waste (potential) CPU cycles all the time simply by not using them. I've got a slew of open programs right now, including Tinderbox, and I think I’m using 40% of one core while the other three twiddle their thumbs.

Still, doing only the work that actually needs to be done feels better.

Update: the consensus view is that wasting CPU cycles is going to be a problem for laptop users who aren’t plugged in. And, increasingly, that’s going to be everybody. So we’re sticking with the old design.

Jan 13 22 2013


If all goes well, this will be the first post on this weblog written in and exported from Tinderbox Six.

There’s still lots to do. Entire sections of this building are still bare planks. There are tools everywhere. But exporting this weblog is an interesting acceptance test; last time I looked, the exporting the weblog involved something like a million attribute references, plus it takes coordination from the rule system, the templating system, all sorts of things.

Conversely, if things have blown up here, let me know how and where.

Jan 13 21 2013

They hate us

Aaron Swartz taught me something yesterday. I think it might be something important.

I was keeping half an eye on his wikipedia page. It’s a waste of time and effort, but what can one do? You visit, have a chat, clean up the weeds, leave a pebble. We screwed up. I screwed up. It doesn’t help, but it can’t hurt.

I've read from some sources that Swartz was Jewish, but they're not sites I'd consider especially reliable. He does have a somewhat Jewish physiognomy, so it's not implausible. Is there any information on this? — Preceding unsigned comment added by (talk) 22:10, 13 January 2013 (UTC)

The wingnuts are attacking. Why are the right-wing zealots descending in force from their anonymous IP addresses and single-purpose accounts? What distracts them from their attacks on Obama and their super bowl plans? Why are they so eager to purge the page of what they sneeringly call “wailing geeks?” Because they hate us.

They’ve hated us since 3rd Grade Reading and 6th Grade Math. They beat us on the playground and they beat us on the street. They formed sex cartels in high school to punish us, they recruited gym teachers and coaches and every fourth-rate teacher they could find to taunt us.

We thought, some of us, that was all behind us. We went to good colleges. They didn’t. We can refactor polynomials and complex systems. They can’t. We can build a railroad, a program, a cathedral and a bazaar, and we can make them run. They can’t.

But they are numerous, and some of them have money, and they hate us all. They call us geeks and nerds and techies. And if you’d like some baseball scores or football analysis, even here in the bluest of blue states, you’d better be prepared to take it with a healthy dose of right-wing sneering at elite liberal pansies.

Every time we make an information appliance, we help them. Every time we make our systems simpler and dumber, we help them. Every time we sell out to people who say, “Don’t make me think!” in order to get some of their money, we help them.

Open systems, open wikis, open source: grand ideas. But they hate us. They will turn our work against us if they can, use the systems we built to mock everything we do and everyone we love. Wikis were our last best hope for something. They have failed. (I was once program chair of ACM Wikisym.)

We have the universities. We have the professions. We don’t have the churches, because the churches have become the refuge of greed and ignorance, lust and hate. We have ourselves. And perhaps we have each other.

They hate us. They fear us, too. There’s going to be a war someday. I still think it starts on the California border when the California National Guard tries to protect a pretty refugee gynecologist from charges of Capital Abortion. But maybe it’ll be the Nevada border — Nevada’s trending blue — or perhaps the border between Virginia and North Carolina.

And it will seem to be about sex and religion and schools and science and freedom. But it’s not that. They hate us, and they will never forgive us.

We will win. We won in 1865. We will again. We always do. And they will never forgive that, either.

by Kami Garcia and Margaret Stohl

I tend to like just about everything I read these days. My stack of urgent reading is so large that it almost always contains something I’m eager to read, and if that disappoints at first, there’s always something else to start. Beautiful Creatures titrates right down to the edge. The movie trailer seemed good, and The Hunger Games and Divergence were so much fun that I hoped for another YA find.

This is the story of a young fellow in Gatlin, South Carolina, who falls for the New Girl In Town. Unlike everyone else in Gatlin, she’s not from here. She’s lived in distant places. She thinks deep thoughts. The other girls hate her.

Oh, and her whole family are supernaturals. And on her 16th birthday, she has to make an irrevocable choice between light and dark.

There are good bits here. I enjoyed the moment when, telling off her sexy and evil older cousin, our heroine shouts, “Get away from my boyfriend, witch!” The co-authors insert themselves neatly into the book as a pair of librarians. The writing is clean for the most part, though an editor should have noticed that, when a character is knocked unconscious at the end of a chapter and looks at “my cell” at the start of next, readers may assume that he’s observing his place of confinement, not his iPhone screen.

But, in the end, Garcia and Stohl never engage the fear they’re writing about. That fear is the mystery of puberty as experienced by pre-adolescents: suddenly, kids you’ve known, kids who were simply “big kids” on the periphery of your life but still part of society, are transformed into something else. They don’t have time for you. Some of them get ugly. Some of them get mean. And the clock is ticking: one day you will wake up and be one of them.

Beyond the big flaw, there are lots of technical issues. Ethan, our hero, tells us a lot about small town Southern life. He has known no other life, but his is an outsider’s description. Scout Finch can get away with this because her dad’s a loner, but Ethan’s family are insiders back to the War of Rebellion. Where does he get his perspective?

It’s not clear to me that this ought to be a Southern Story; formally, it’s a New England story (the past rises up to kill you) and not a Southern Gothic (there is a terrible secret). And there are lots of little things: when our best friend ditches school vacation at Bible Camp and heads to New York for a week with a girlfriend’s older, supernaturally hot cousin, nobody appears to ask him the question that’s got to come first amongst the sophomore boys: how far did you get? This whole book is about sex, but nobody is ever permitted to think about it.

Note to readers: I’m in a foul, foul mood. I did finish the book, despite its length and in spite of all temptations to belong to other nations. Perhaps on another day I’d have overlooked more faults and seen more virtues.

Jan 13 18 2013

After Aaron

Quinn Norton’s eulogy.

This is the written version of my eulogy for Aaron. I would like to not write any more eulogies for a while.

A brave speech. "He was scared and self conscious, funny, greedy, and petty, loving, curious, hopeful, and strange. He was irreducible, difficult."

Also, a blast from a voice I haven’t heard in too long. AKMA writes:

I wonder why I haven’t heard any theological, ecclesiastical, synagogal leaders speaking about Aaron’s struggle against injustice, and the overwhelming stress that seems to have eclipsed his determination.

Of course, in my circles we mostly expect to hear from theological and ecclesiastical leaders when they have an opportunity to oppose science or sex, or maybe to support a Republican war. To say this is to be tough on AKMA and Ayjay, I guess, and on one or two of my friends who would like to believe. And it’s reading the Friends and the Unitarians out of meeting, though I’d argue that train has already left the station. (Notice that the NRA expected everyone to believe that Sidwell Friends School employs armed guards, and until yesterday everyone pretty much did. What parts of “Friends” did people overlook?) The “unwavering, unflinching commitment to encourage practices of critical deliberation and exploratory reasoning” always seems to vanish about the time that the church can be used to elect someone who will cut taxes and support Republican values.

I hope that you too are wondering why the churches are silent. I hope that perhaps this was just a respectful interval of restraint, allowing a beautiful life of integrity and brilliance and sorrow to hold centre stage for a while — and that soon we hear the churches speaking out thunderously on behalf of the commons, of justice, of human well-being rather than corporate profits.

I made a nifty pot roast Sunday night.

You take a piece of beef chuck, or maybe flanken, and sear it very well in a very hot dutch oven. When it’s nicely browned, you put it on a plate, drain excess fat, and soften a lot of sliced onion and some sliced carrots until they begin to caramelize. A little bacon or pancetta at this stage is not necessarily amiss. Then the meat goes back in the pot.

Got some leftover wine? Throw it in, reduce it. Doesn’t matter if it’s red or white. No wine? Skip it.

Throw in some tomatoes, maybe a couple of potatoes, some peppercorns, a couple of bay leaves. Add stock about half way up the meat. Chicken stock will do fine. No stock? Use water. (Water is probably better than using stock from a box.) Heat to boil. Then put it in a 300° oven and watch a football game. Or two.

Chuck and flanken work great; after a few hours, the meat is falling apart but it’s flavorful and not mushy. The key is the mix of fat and meat and its distribution through the roast; the fat cooks out and you’re left with lots of flavor and tenderness that you can eat like a stew or turn into a ragu.

There should be a corresponding cut lamb. Right? But what is it? Lamb shoulder doesn’t work the same way. It’s too lean, and it seizes up where the beef falls apart. I suppose lamb shanks are close. But what’s the right thing to use? Email me.

Jan 13 10 2013

Aaron Swartz

The first time Aaron came to Eastgate, he could barely see over the receptionist’s counter. We’d been exchanging email about the RSS standard for some time; I needed RSS for Tinderbox 1, the standard was bitterly contested, and in the technical flamewar he’d distinguished himself as the voice of reason, of getting the engineering right and ignoring the feuds and fracases.

I had no idea he was 14. When he called to set up a lunch meeting, explaining he was in Boston for a conference, I figured he was a 40-ish software engineer, someone who worked at IBM or DEC.

He was sharp and incisive and impatient. He knew everyone, even then, and was generous with introductions and candid in talking about his colleagues. He had school trouble, as you’d expect, but his parents and his school gave him lots of rein and it worked out pretty well. Instead of a few boring years on the Hellmouth, he spent his time with the stars of the Web. He did what I should have done.

He came to the Turkey Snow Dinner, the outdoor grilled turkey in two feet of Boston snow, the dinner where the Norwegians got their car stuck in the driveway. He’d sent his regrets – he had to catch a plane – but everything was cancelled and so there he was and a good time was had by all.

He had little patience for weakness and less for bugs. He’s one of two people I’ve met who really believed in flawless code, and he was the one who knew what he was doing.

He went to Stanford for a year, spent the summer on an incubator project, then switched to his roommate’s project. That was Reddit. They sold it, he cashed out. He was young and handsome and smart and rich and the world was all before him.

And now it’s not.


People point to the old blog posts about being depressed. But he was 17 then. C’mon.

People point to the JSTOR trial and the fear of prison. And that’s a big deal. But there’s another parallel between us: when I was in my late teens, I spent a fair amount of time thinking about prison. There was a war on, my choices seemed to be jail or exile and I wasn’t sure I was up to jail. A smart Quaker girl at school slapped that down real fast. “Thoreau managed. Ghandi was small and sick. You’ll be fine.” It never came to that – I got my 1-O – but she was not wrong.

No simple answers. A last lesson, I guess, and like most of Aaron’s lessons, perhaps it’ll make some sense later. It doesn’t now.


I’ve been writing model-view-controller applications since Smalltalk-80 and the Tektronix 4404. I’m a big believer in the Gang of Four. I refactor for lunch.

But I’m getting very confused in my dotage. What are controllers for, anyway? Apple wants them to be mediators between model and view, and that makes sense for generic view parts like buttons where you don’t want to widget to know anything about the model.

But what are we supposed to do with, say, TinderboxMapItemView? The whole point of Tinderbox visualization is to pack a lot of visual information about difference facets of complex note objects into a small are of screen real estate. Some things that we need to unpack for displaying one note, for example, include:

  • DisplayName
  • Name
  • Subtitle
  • Text
  • Child Count
  • Text length
  • Color
  • Accent color
  • Pattern (which might be a graph of any two attributes!)
  • Fill
  • Shadow (color, distance, blur)
  • Font (and font size) for Title and Text
  • Opacity
  • Bold
  • Strike through
  • Checked

So, do we want to send the view a huge bundle of assorted properties? We already have a bundle of properties: it’s the object! And reuse is an open question here, too: are we more likely to want to reuse the model or the view?

So I’ve always let the view know about class Node and class Hypertext. In PowerPlant, LViews did double duty, combining the roles of View and Controller, and that was not always a good thing. Cocoa wants to use separate controllers, and that sounds good.

I don’t understand the Cocoa implementation. In particular, behavior is supposed to be in the Controller, but the Controller doesn’t receive actions and events. Instead, the View gets actions and events. Sure, we could forward them all to the controller, which gives you a partitioning, and that makes sense for generic views. But, if we’re letting the view know a little about class Node anyway, what do we gain by forwarding all the actions and events to another class?

Someone out there: set me right.

class TanseyTabView : NSObject {...

It’s taken something like six years, but yesterday I finally started work on an idea proposed by Frank Tansey at an early Tinderbox Weekend. The idea is to add “tabs” to Tinderbox views, much as Firefox added them to the Web browser. The tab keeps track of the view settings, and you can quickly move between an outline of the whole document and a map of the part you’re exploring right now.

It’s a good idea, and fits naturally with the current preference for one-window applications. Storyspace and Tinderbox have always embraced tons of windows. I’ve never been convinced that having lots of windows is very bad, but as people grow accustomed to single-window documents they forget that multiple windows are even possible. The move to extreme screens — tiny phone screens, gigantic multi-screen consoles — adds even more tension to the mix.

Jan 13 7 2013

Word In A Box

Graphic design and typography friends: What is the best way to vertically align a word in a box?

Word In A Box

You could say, “put the baseline in the center of the box.” Or, you might say, “center the bounding rectangle of the word.” Perhaps you’ll say something like “Set the baseline half the x-height below the centerline,” which would make me cry. But perhaps that’s the answer. (As you can tell, I’m deep into Tinderbox Six design, and there have been tears aplenty and there will be more. Bring it on.)

But what if the text is all caps? Then everything is above the center, and the bottom half is empty. Here, we have nine characters but only two descenders; do the rare descenders balance the ascenders?

Constraints: the solution has to be computational, and should ideally apply reasonably to arbitrary text and arbitrary fonts. Email me.