Vom Kopf zum Blatt

Neun bis dreißig Köpfe auf einer Fläche, jeder an seinem Platz, jeder in derselben Größe – und einer davon jederzeit groß in der Mitte. Das ist weniger Verwaltung, als es klingt: das Blatt ist ein Raster, ein Maßstab, eine Reihenfolge und eine Zahl.

Das Raster

Die Spaltenzahl springt an vier festen Schwellen – 560, 900, 1300, 1800 Pixel. Keine Formel, sondern eine Tabelle: eine Formel träfe irgendwann eine Breite, bei der sie zwei Spalten oder elf vorschlägt, und beides ist kein Blatt. Die Reihen ergeben sich danach aus einer einzigen Bedingung – die Zellen sollen ungefähr quadratisch bleiben.

Im Zweifel lieber eine Spalte mehr als große Köpfe mit Luft drumherum. Ein Kopf, der im Breitbild allein in einer flachen Kachel steht, sieht verloren aus; sechs kleine Köpfe in einer Reihe sehen nach Blatt aus.

Der Seed einer Zelle ist blattSeed + r · spalten + c. Benachbarte Zellen haben also benachbarte Seeds – genau der Fall, für den der Generator im Kapitel Zufall acht Züge wegwirft. Ohne das Aufwärmen stünden hier Reihen von Verwandten.

Raumbedarf gegen platzIn

Der Stil sagt, was ein Kopf braucht (raum(dna)), die Zelle sagt, was sie hergibt (platzIn). Beide rechnen in Kopfeinheiten, damit sie überhaupt vergleichbar sind.

Nach unten wird nicht gemessen: dort steht der Name, und keine Frisur reicht so weit. Nach oben und zur Seite schon – der Afro ist rund und deutlich breiter als der Schädel, der Knoten eines Dutts sitzt obendrauf, und eine Hutkrempe ragt über jeden Kopf hinaus.

Verlangt eine Frisur mehr, als ihre Zelle hergibt, wird nicht dieser eine Kopf kleiner, sondern das ganze Blatt. Neun Köpfe in neun Maßstäben sehen aus wie ein Fehler; ein etwas kleineres Blatt sieht nach Absicht aus.

Meistens kommt 1 heraus. Die Zelle ist so bemessen, dass die üblichen Frisuren hineinpassen; der Faktor greift erst bei den größten Afro-Kugeln – und dann für alle.

Die Zeichenreihenfolge ist Teil der Korrektheit

Ein Kopf wird nicht zusammengesetzt, sondern gestapelt. Es gibt keine Verdeckungsrechnung, keinen Tiefenpuffer und keine Masken zwischen den Zügen – jeder Zug darf übermalen, was unter ihm liegt. Die Ordnung ist deshalb kein Ablauf, sondern eine Aussage darüber, was wovor liegt. (Die eine Ausnahme bleibt in einem Zug: der Wangenbogen beschneidet das Auge, zu dem er gehört, siehe Merkmale.)

Sie stand lange nirgends. Sie war die Reihenfolge von siebzehn Aufrufen in zeichneGesicht, und wer einen davon zwei Zeilen höher schob, verschob eine Verdeckung – ohne dass ihm etwas sagte, dass er gerade einen Vertrag angefasst hatte. Heute nennt jeder Zug seine Ebene, und die Ebenen stehen als Liste:

Die Züge werden gesammelt, stabil nach Ebene sortiert und dann gezeichnet. Stabil heißt: innerhalb einer Ebene gilt weiter, wer zuerst gesammelt wurde – sonst läge die Kontur unter ihrer eigenen Fläche und wäre weg.

EbeneWarum dort
halsGanz hinten. Der Kopf sitzt darauf und deckt den Ansatz.
hinter-dem-kopfZöpfe, die Afro-Kugel. Sie werden vor der Kopffläche gezeichnet und von ihr zur Hälfte verdeckt – das ist der ganze Trick.
ohrenDas abgewandte Ohr sitzt seitlich am Schädel, also unter seiner Fläche.
kopfDer Deckel über allem Hinteren – und die Kontur darüber, sonst frisst der Rand der Fläche die Linie an.
zugewandtes-ohrDas zugewandte Ohr liegt vor der Wange: dreht der Kopf, wandert sein Anker hinter die Silhouette, und die Kopffläche biss ihm die Wurzel ab. Welches Ohr hier landet, sagt seine Normale – nicht die Seite im Bild.
hautBacken, Augenringe, Schraffur, Stirnfalten: Farbe und blasse Nebenlinien auf der Haut, unter allen Zügen.
bartUnter der Nase, auch in der Ordnung. Was die Nase überlappt, verdeckt sie.
fernes-augeDas Auge auf der abgewandten Seite. Welches das ist, sagt seine Tiefe – nicht das Vorzeichen der Drehung.
naseSie hat Volumen und stellt sich frei – also verdeckt sie das Auge hinter sich.
nahes-augeVor der Nase gezeichnet radierte sie auch dieses weg.
mundÜber dem Bart, unter dem Rest.
frisurHaar und Kopfbedeckung: die Schale liegt auf dem Schädel, nicht darunter.
aufgesetztOhrring, Pflaster – am Kopf, aber nicht Teil von ihm.
sternaugenDie reinen Sternaugen (funkeln) und nur sie: keine Augenform, sondern ein Zeichen auf dem Kopf – größer als jedes Auge, in eigener Farbe. Unter einer Frisur läge es angeschnitten da. Die Braue bleibt unten beim Gesicht und wird vom Stern verdeckt.
davorVor dem Gesicht und deshalb über allem – auch über der Mütze, die auf dem Schädel sitzt und nicht davor.
Die Nase, die das Auge wegradiert

Symptom: Bei gedrehtem Kopf fehlt dem vorderen Auge ein Stück, als wäre es angeschnitten. Ursache: Die Nase ist keine Linie, sondern eine Form mit Fläche. Vor beiden Augen gezeichnet deckt sie nicht nur das ferne, sondern auch das nahe zu. Lösung: Drei Ebenen verschränken sich: fernes Auge, Nase, nahes Auge. Welches der beiden das ferne ist, entscheidet die Tiefe der Augen-Felder, nicht das Vorzeichen der Drehung – und eine Probe hält es fest: über vierhundert Seeds muss das zuletzt gezeichnete Auge das mit dem größeren z sein.

Die Großansicht ist eine Zahl

Kein zweites Element, kein Modal, kein zweites Canvas. fokus.t läuft zwischen 0 (der Kopf sitzt in seiner Zelle) und 1 (er steht in der Mitte), und der Ort wird daraus gerechnet.

Weil ohnehin jedes Bild neu gezeichnet wird – die Köpfe folgen dem Zeiger –, ist das der einfachere Weg und nebenbei der weichere: t nähert sich seinem Ziel jedes Bild um einen festen Anteil des Restwegs. Das ist in beide Richtungen „schnell los, weich an" und lässt sich mitten in der Bewegung umkehren, ohne dass etwas springt.

Der Schleier über dem Raster ist papierfarben, nicht grau. Das Blatt tritt zurück, statt dass ein Vorhang davorfällt – und am Ende deckt er ganz, damit hinter dem großen Kopf kein Raster durchschimmert.

Die Werkstatt: ein Kopf, sechzehn Würfel

Aus der Großansicht führt ein Weg heraus. Auf /werkstatt.html?kopf=118317 steht dieselbe Person allein auf dem Papier, und neben ihr ein Würfel je Merkmal: die Augen ohne die Nase, die Frisur ohne den Kragen.

Dass das überhaupt geht, ist keine neue Rechnung, sondern eine alte Entscheidung: zeichneKopf nimmt eine DNA entgegen und keinen Seed, und der Kopfdaten-Cache des Stils hängt am DNA-Objekt, nicht an dessen Seed. Eine gebaute DNA mit geändertem Merkmal bekommt deshalb ihre eigene Schale, ihre eigene Palette und ihren eigenen Raumbedarf.

Neu ist, was ein bearbeiteter Kopf IST. Auf dem Blatt ist ein Seed die Adresse einer Person; wer ein Merkmal neu würfelt, verlässt diese Adresse. Ein Wurf ist deshalb der Seed plus das Wenige, was von ihm abweicht – und beides zusammen passt wieder in eine Zeile:

?kopf=118317&auge=stern&haar=igel&farben=2

Zwei Arten Abweichung, verschieden aufgeschrieben. Merkmale haben ein Vokabular, bei ihnen steht der Wert da. Das ist lesbar, kurz und stabil: ein gewürfeltes Merkmal wird nie wieder nachgerechnet und kann sich deshalb auch nicht unter der Hand ändern, wenn nebenan ein anderer Würfel fällt. Kopfform, Proportionen, Haltung und Farben haben keins – acht Kommazahlen in einer Adresse wären unleserlich und beim ersten Runden kaputt. Bei ihnen steht, der wievielte Wurf gilt; der Wert kommt aus strom(seed, 'kopfform#3').

Ein Merkmal ist aber nicht nur sein Wort. Zu jedem Wort würfelt der Stil eine Handschrift – wie viele Zacken der Igel hat, welche Krempe der Hut, wie voll die Haube liegt –, und die soll mit jedem Wurf neu fallen. Hinge sie allein am Wort, gäbe es für diesen Kopf genau EINEN Hut, und der Würfel zeigte ihn wieder und wieder: kein Würfel, ein Schalter. Deshalb steht hinter dem Wort, wenn nötig, die Fassung: haar=igel.3 ist der Igel aus dem dritten Wurf auf die Frisur. Die erste Fassung steht ohne Zähler da, damit jeder Link von vorher denselben Kopf zeigt wie bisher.

Ein Würfel, ein Merkmal. Was daneben steht, bleibt stehen – auch die Handschrift des Stils. Deshalb würfelt der Augen-Würfel Form, Pupille, Größenunterschied und Sternzacken zusammen (siehe Ströme), und deshalb werden neue Proportionen so lange verworfen, bis ihre Lage zu den gewählten Merkmalen passt.

Eine Ausnahme gibt es, und sie steht hier, weil sie eine ist: der Ton der reinen Sternaugen. Er kommt aus einer eigenen Tonleiter und steht in keinem der fünf Farbgene. Er hört deshalb auf ZWEI Würfel – auf den der Augen, weil er zum Stern gehört, und auf den der Farben, weil er auf so einem Kopf die lauteste Farbe im Bild ist. Wer an den Farben gedreht hat, behält seinen Ton danach auch über eine neue Sternform hinweg.

Die Herausforderung ist nicht die Rechnung, sondern die MENGE. Ein Kopf besteht aus über vierzig Zahlen und zwölf Merkmalen; als Liste von Reglern wäre das ein Cockpit. Drei Entscheidungen halten sie klein.

EntscheidungWirkung
Sechzehn Gruppen statt vierzig Werte Gewürfelt wird auf der Ebene, in der ein Mensch denkt: „Augen", nicht „Augenform, Pupillengröße, Jitter, Sternzacken"
Das Bild ist das Menü Sechs Stellen auf dem Kopf würfeln ihr Merkmal: Augen, Nase, Mund, Backen, Frisur, Kragen. Die Anker kommen aus dem Layout und laufen durch dieselbe Sicht wie die Zeichnung – eine geratene zweite Geometrie stimmte bei jeder zweiten Drehung nicht mehr
Die Liste ist die zweite, volle Hand Jede Gruppe, jeder Wert im Klartext, und der Weg für Tastatur und Vorlesestimme – das Canvas ist für beide ein leeres Rechteck

Nicht auf dem Kopf liegen Brauen, Zeichen, Brille, Bart und Zierrat: eine Trefferzone für die Brauen NEBEN einer für die Augen wäre ein Ratespiel, denn zwischen beiden liegt ein Zehntel Kopf. Die Kopfbedeckung fehlt aus demselben Grund – sie sitzt dort, wo auch die Frisur sitzt.

Ein Würfel, der nichts zu bieten hat, wird abgeschaltet und sagt, warum: über einer Haarmasse ist jede Kopfbedeckung außer „nichts" gesperrt. Den Grund liefert der Katalog (beide Richtungen), den Satz die Seite. Gezogen wird OHNE den Wert, der gerade dasteht – ein Würfel, der dasselbe noch einmal zeigt, wirkt kaputt –, es sei denn, der Wert hat eine sichtbare Handschrift: ein Stern, ein Hut, eine Frisur dürfen wiederkommen, denn in neuer Fassung sind sie ein anderer Stern, ein anderer Hut. Welche Werte das sind, steht als Liste in core/wurf.ts. Und gezogen wird FLACH: die Gewichte des Katalogs sind für das Blatt gemacht, wo von neun Köpfen einer einen Hut tragen soll und „keine" bei Brille 8, Bart 12 und Kopfbedeckung 9 wiegt. Wer in der Werkstatt auf den Bart-Würfel drückt, will aber einen Bart sehen; mit den Blattgewichten wären drei von vier Würfen ein Wurf ins Leere. Hier zählt jeder Wert gleich, nur die Passung zur Lage des Gesichts bleibt bevorzugt.

Der Weg zurück führt auf das Blatt, von dem man kam: der Verweis vom Blatt bringt dessen Seed mit (&blatt=…), die Werkstatt hält ihn in ihrer Adresse und gibt ihn mit dem Kopf zurück – /?blatt=…&kopf=… baut genau dieses Blatt und öffnet den Kopf gleich groß. Der Wechsel zwischen beiden Seiten ist eine Blende (@view-transition), und damit sie auf ein fertiges Bild blendet, steht das Skript beider Seiten render-blockend im Kopf.

Und die Sprache? Die Doku trägt sie im PFAD – /docs/ ist deutsch, /docs/en/ englisch –, damit ein verschickter Link beim Empfänger so ankommt, wie er abgeschickt wurde. Ein Dokument hat eine Fassung. Die Werkstatt ist keins: ihre Adresse beschreibt einen KOPF, und der ist in jeder Sprache derselbe. Hier entscheidet deshalb der Browser – Deutsch für den, der Deutsch eingestellt hat, sonst Englisch. Wer es festhalten will, hängt ?sprache=de oder ?sprache=en an; dann steht es in der Adresse und reist mit ihr.

Der Bogen: ein Blatt, das man mitnehmen kann

Auf dem Blatt ist das Papier das FENSTER. Neun Köpfe verteilen sich auf der Fläche, die gerade da ist; ein schmales Fenster gibt ein anderes Raster als ein breites. Das ist richtig für etwas, das man durchblättert.

In der Werkstatt entsteht ein einzelnes Bild, und eines, das den Browser verlässt. Ein Bild, dessen Format vom Fenster kommt, ist beim Herunterladen ein Bildschirmfoto: auf dem Telefon hoch, auf dem Schreibtisch breit, und nie das, was man gesehen hat. Der Bogen hat deshalb ein Format – DIN, hochkant, Höhe = Breite · √2 – und eigene Einheiten. Er ist 600 Einheiten breit, egal wie groß er zu sehen ist; den Maßstab setzt der Aufrufer in die Fläche, bevor er zeichnet.

Eine Funktion für Bildschirm und Abzug. Der Bildschirm ruft sie mit dem Maßstab der Anzeige auf, die gesicherte Datei mit einem größeren – 1500 px breit, also f = 2,5. Zwei Zeichenwege liefen früher oder später auseinander, und zwar genau dort, wo niemand hinsieht: im heruntergeladenen Bild.

Der Kopf hängt darin weiter am Raumbedarf des Stils – ein Hut braucht mehr Platz als ein blanker Schädel –, aber nicht mehr an der Fenstergröße. Der Maßstab wird deshalb bei jedem Wurf einmal gerechnet und nicht bei jedem Bild.

Der Name steht unten im Rand, klein, wie eine Signatur. Er hängt am BOGEN und nicht am Kinn: ein Name, der mit der Frisur wandert, sitzt unter einem Hut tiefer als unter einem blanken Schädel.

Kante und Schatten sind gezeichnet – mit demselben Stift wie das Kinn und derselben Presse, die auch die Haut neben ihre Kontur setzt. Ein Rechteck mit exakter Ecke wäre das einzige exakte Ding auf einer Seite aus lauter Handstrichen, und ein weicher CSS-Schatten das einzige Stück Fotografie. Der Schatten ist deshalb eine zweite Platte, die nicht sitzt: derselbe Umriss, ein Stück versetzt, in einem dunkleren Ton. Das Papier wird auf diesen Umriss beschnitten, sonst stünde die gezeichnete Kante auf einem exakten Rechteck aus Papier und man sähe beide.

Vier Striche, kein Rechteck: die Ecken sind spitz, und jeder Strich läuft ein Stück über sie hinaus – so, wie eine Hand einen Kasten zieht. Sie hält nicht in der Ecke an, sie geht darüber. Ein abgerundeter Umriss sah aus wie ein Kartenstapel, und genau das ist ein Bogen nicht.

Der Bogen KOCHT dabei nicht. Die Linien eines Gesichts setzen achtmal in der Sekunde neu an, weil ein Gesicht lebt; ein Blatt Papier tut das nicht, und ein zitternder Rahmen um ein ruhiges Bild wäre der Rahmen, den man ansieht.

Gehört zum TischGehört ins Bild
Kante und Schatten des Bogens Papier, Korn, Vignette
Die Bewegung – Blick, Lidschlag, Atem Die Ruhe: die Pose der DNA, offene Augen, kein Blick zur Seite
Liste, Pfeile, Leiste Der Kopf und sein Name

Die zweite Zeile ist die wichtigere. Der Kopf in der Werkstatt lebt – er folgt dem Zeiger, blinzelt, atmet. Ein Bild mitten in der Bewegung gäbe zu derselben Adresse bei jedem Klick ein anderes, und dass eine Adresse einen Kopf bezeichnet, ist die Zusage, an der hier alles hängt. Der Dateiname ist dieselbe Adresse in einer Schreibweise, die ein Dateisystem verträgt: aus ?kopf=118317&auge=stern wird tomu-118317-auge-stern.png.

Und auf dem Telefon? Dort steht statt der sechzehn Zeilen nur EINE, und zwei Pfeile blättern durch. Eine Liste, die länger ist als das Gerät hoch, ist kein Überblick, sondern ein Schacht: der Kopf, an dem man würfelt, wäre beim Scrollen aus dem Bild. Welche Zeile gemeint ist, entscheidet die Rechnung; OB nur eine zu sehen ist, entscheidet das Stilblatt – die Rechnung soll nicht wissen müssen, wie breit das Fenster ist. Wer auf dem Bild ein Merkmal antippt, findet die Zeile darunter schon bei diesem Merkmal.

Die Namen sind kein Teil des Bildes

Sie liegen als <span> über dem Canvas, an genau der Stelle, an der das Canvas sie sonst gemalt hätte – den Ort rechnet die App ohnehin aus, für den Zoom.

Gemalter Text

Symptom: Ein Name lässt sich nicht markieren, nicht kopieren, nicht suchen, und eine Vorlesesoftware findet auf dem Blatt nichts als ein leeres Rechteck. Ursache: Gemalter Text ist ein Bild. Lösung: Text bleibt Text. Das Canvas trägt ein aria-label, die Namen stehen darüber im DOM.

Der Gewinn ist nicht nur das Kopieren. Der Name in der Großansicht bekommt damit eine eigene Bewegung: er kommt einen Hauch von unten nach, wenn der Kopf schon steht, und geht schneller, als er kam. Ein Name, der so lange bräuchte wie der Kopf, würde mit ihm um die Aufmerksamkeit streiten.

Auf dem Bogen ist es umgekehrt, und aus demselben Grund: dieses Bild verlässt den Browser. Ein Name, der nur im DOM steht, käme beim Empfänger nicht an – ein Kopf ohne Adresse. Dort ist der Name deshalb gemalt, und die Vorlesestimme hört ihn im aria-label des Canvas.

Zwei Namen, nicht einer: wunsch ist, was dort stehen soll, gezeigt, was gerade dort steht. Die App fragt jedes Bild neu an – sechzig Mal in der Sekunde denselben Wunsch. Ohne diese Trennung liefe in jedem Bild ein neues Ausblenden an, und das Einblenden käme nie dran; der Name bliebe für immer halb da.

Prüfen ohne Bildschirm

Der Entwicklungsbau legt vier Griffe an window.presse: wuerfle(seed) stellt ein bestimmtes Blatt, schaue(x, y, s) rechnet die Federn ohne Bildschleife weiter, zellen() sagt, wo welcher Kopf sitzt und was er trägt, und abzug(name) schickt das Blatt in voller Auflösung per POST /__abzug an den Server, der es unter abzuege/ ablegt.

Die unsichtbare Seite steht still

Symptom: Eine automatisierte Prüfung sieht Köpfe, die stur geradeaus schauen – ob sie dem Zeiger folgen, lässt sich nur behaupten. Ursache: Ohne sichtbare Seite hält der Browser requestAnimationFrame an. Es gibt niemanden, der das nächste Bild malt. Lösung: schaue() rechnet die Federn in Schritten von 1/60 Sekunde selbst weiter und zeichnet einmal. Für den Abzug werden die Namen einmalig ins Canvas gemalt – das nächste Bild wischt sie wieder weg.

Der ganze Zweig existiert nur unter import.meta.env.DEV; im Bündel ist er entfernt. Ein Griff, der im Auslieferungsstand mitläuft, ist keine Prüfhilfe mehr, sondern eine Schnittstelle.