Florilegium: Procedureel gegenereerde Delfts blauwe bloemmarges voor LuaLaTeX

Oorsprong

Wat is Florilegium?

Florilegium genereert procedurele, Delfts blauwe bloemmarges voor LaTeX. Er worden geen afbeeldingen, geïmporteerde paden of externe assets gebruikt. Elk bloemblad, blad en stengel is een parametrische curve die in Lua wordt berekend terwijl de pagina wordt geschreven. De tekening is uitgevoerd in een aquarelstijl en wordt direct in de PDF geschreven, waardoor elke pagina zijn eigen unieke tuin krijgt.

Compositievormen

Er zijn twee manieren waarop de compositie kan worden opgebouwd:

  • Authored (Handmatig): Stengels, bladeren en bloemen worden op vaste posities geplaatst, waarbij elke parameter wordt gesampled. Dit is geoptimaliseerd voor A4 met een marge van 68 mm.
  • Grown (Gegroeid): Een plant groeit via een "greedy space-filling loop" om precies in de beschikbare ruimte van de pagina te passen. Dit past zich aan de paginalay-out aan en vult ook de vrije ruimte onder de tekst op de laatste pagina.

Functionaliteiten

Interactie met de tekst

De marges kunnen reageren op de inhoud van het document:

  • Initialen: Met \florilegiuminitial[5]{E} wordt de eerste letter van een paragraaf in een tegel van vijf regels hoog geplaatst. De omtrek van de letter wordt gelezen uit een OpenType-lettertype (standaard Latin Modern Bold) en geschilderd als een bloemblad. Een klimplant weeft over en onder de lijnen van de letter.
  • Bloemen bij koppen: Met de optie sections krijgt elke genummerde sectie en subsectie een bloem in de marge naast de kop. Deze worden getekend in de koperkleur van de accenten.
  • Specifieke bloemen: Met \florilegiumbloom kan er een bloem naast een specifieke regel worden geplaatst. Met \florilegiumbloom[lily] kan een specifiek motief uit de tuin worden opgevraagd.
  • Seizoenen: Met de optie aging verandert de tuin van seizoen naarmate het document vordert: van de lente op de eerste pagina (voornamelijk knoppen en kleine bleke bladeren) tot de herfst op de laatste pagina (zaadhoofden, vallende bloemblaadjes en koperkleurige bladeren). De leeftijd kan ook handmatig worden ingesteld met \florilegiumage{0.8}.

Bezoekers

De meeste pagina's bevatten kleine details in de vorm van bezoekers: vlinders, bijen, een slak die een stengel opklimt, of (ongeveer één op vijf pagina's) een vogel op een takje. Deze worden gegenereerd uit een eigen random-stream. De optie novisitors kan deze elementen uitschakelen.

Kleurgebruik

Het volledige kleurenpalet is afgeleid van één basiskleur (ink), zoals Delfts blauw, sepia, groen, karmozijnrood, violet of teal. Het verloop van de donkerste lijn naar de lichtste wassing wordt berekend in de OKLCH-kleurruimte, zodat de lichte tinten nooit grijs uitslaan.

Implementatie in PostScript

Er bestaat een versie in puur PostScript (postscript/florilegium.ps). Dit is één zelfstandig bestand waarbij Ghostscript of een printer de bloemblaadjes berekent tijdens de interpretatie van de pagina.

Verschillen met de LaTeX-versie:

  • Lagen: Omdat PostScript geen lagen kent, wordt alles in een specifieke volgorde opgebouwd en opgeslagen in lijsten per laag, die aan het einde worden afgespeeld.
  • Transparantie: PostScript ondersteunt geen transparantie. Ghostscript kan dit oplossen met de vlag -dALLOWPSTRANSPARENCY. Zonder deze vlag worden translucente vullingen gemengd met de onderliggende kleur en ondoorzichtig geschilderd.
  • Willekeur: De generator gebruikt 32-bit integer rekenkunde (Park-Miller), waardoor een specifieke 'seed' in PostScript een andere tuin oplevert dan dezelfde 'seed' in LaTeX.
  • Tekst: Het bestand zet zijn eigen tekst in Times. Het herkent koppen en het einde van de tekst, waardoor koperbloemen bij koppen en de tuin onder de laatste regel gewoon werken. Initialen, animaties en handmatige composities ontbreken echter.

Installatie en Gebruik

Bouwen

Het project wordt gecompileerd met LuaLaTeX. Voor de meeste bestanden is één pass voldoende; showcase.tex vereist twee passes voor de seizoensberekening.

Beschikbare make-commando's:

  • make: Genereert de drie PDF's.
  • make seed-7: Genereert één pagina op basis van seed 7.
  • make gallery: Genereert afbeeldingen van seeds, inkten en seizoenen (vereist Python3, Pillow, pdftoppm).
  • make grow-6: Genereert een groeianimatie van seed 6 (vereist ffmpeg).
  • make grow-6 EXPLAIN=1: Idem, maar met markering van de vrije schijven.

Gebruikers zonder TeX-installatie kunnen Docker gebruiken:

docker build -t florilegium-tex tools
make RUN=tools/in-docker

Het is ook mogelijk om florilegium.sty, de zes .lua bestanden en een .tex bestand in een Overleaf-project te plaatsen en de compiler op LuaLaTeX te zetten.

Gebruik in eigen documenten

\usepackage[grown]{florilegium} % Of \usepackage{florilegium} voor de 'authored' versie
% Opties voor 'grown': sections (bloemen bij koppen), aging (twee runs), novisitors (geen dieren)

\definecolor{ink}{HTML}{5B2A1F}      % Optioneel: de hoofdkleur (voorbeeld is sepia)
\definecolor{accent}{HTML}{B4662F}   % Optioneel: de koperkleur voor haarlijnen

...
\florilegiuminitial[4]{T}his paragraph starts with a decorated T.
... een bloem in de marge naast deze regel \florilegiumbloom ...
\florilegiumage{0.8}                 % Alleen voor 'grown': herfst vanaf hier
\florilegiumtextend                  % Alleen voor 'grown': aan het einde van de tekst

Individuele elementen kunnen ook binnen een TikZ-picture worden getekend:

\begin{tikzpicture}
  \begin{scope}[shift={(2,2)},rotate=20]\florilegiumdraw{flower}{1.3}\end{scope}
  \begin{scope}[shift={(5,0)}]\florilegiumdraw{leaf}{3.0, {depth=0.6}}\end{scope}
  \begin{scope}[shift={(8,1)}]\florilegiumdraw{ghost}{"lily", {s=1.4}}\end{scope}
  \begin{scope}[shift={(11,1)}]\florilegiumdraw{butterfly}{1.5}\end{scope}
\end{tikzpicture}

Technische Werking

Tekenen (ink.lua)

Alle geometrie wordt berekend in Lua en geschreven als PDF-padoperatoren in één literal node per pagina; TeX voert geen rekenwerk uit. Kleuren komen uit een toonramp afgeleid van de kleur ink. Tapered strokes (uiteunlopende lijnen) worden gevormd door twee verschoven Béziercurves.

Primitieven (flora.lua)

Elementen worden geschilderd in de volgorde van een aquarellist: een vlakke wassing, donkerdere vlekken, pigmentophoping bij de randen, witte strepen en fijne nerven, met vrijwel geen contourlijnen. De primitieven omvatten:

  • Bloemblaadjes, sterlelies, knoppen en klokbloemen.
  • Gelobde en hele bladeren.
  • Vergeet-mij-nietjes, vertakte twijgen, schermen en ranken.
  • Vlinders, bijen, slakken en een vogel.
  • Koperen glinsteringen, rozetten en het klimopblad-fleuron.

Authored composition (authored.lua)

Een plant groeit vanuit een wortel linksonder. Drie stengels volgen handgekozen controlepunten en een vierde stengel vormt de footer onderaan de pagina. Bladeren en andere motieven worden geplaatst op fracties van de stengels, waarbij elke bloem herleidbaar is naar de wortel.

Grown composition (grow.lua)

Gebaseerd op Computer-Generated Floral Ornament (Wong, Zongker & Salesin, SIGGRAPH 1998). Stengels zwaaien omhoog als "smooth noise". Vervolgens wordt herhaaldelijk de grootste vrije schijf gezocht binnen bereik van een stengel, waarna een passend motief wordt gekozen en er een tak naar wordt gegroeid. Dit proces vult eerst de grote gaten en eindigt met kleine details zoals knoppen.

Pagina-analyse (florilegium.lua)

Koppen of \florilegiumbloom plaatsen onzichtbare markeringen in de tekst. Bij het genereren van de pagina wordt de box node voor node doorlopen om de exacte hoogte van deze markeringen te bepalen, zodat de tuin de bloemen op de juiste positie plaatst.

Initialen (initial.lua)

De omtrek van de letter wordt via luaotfload gelezen als Bézier-segmenten. Deze worden omgezet naar polygonen voor een "even-odd" binnentest. Een raster van afstanden tot de letter en het frame bepaalt waar de grootste gaten zijn voor de bloemen. De klimplant is een Catmull-Rom curve die over en onder de letterlijnen weeft.

Opmerking: Procedureel is niet hetzelfde als willekeurig. De 'seed' is afgeleid van het paginanummer, waardoor pagina n altijd tuin n krijgt. Dit zorgt ervoor dat het document stabiel blijft tijdens het zetproces.

Licentie

MIT.