Silbentrennung ist in den meisten westlichen Sprachen notwendig, um ein
einigermaßen gutes Erscheinungsbild für schmale Texte zu haben. Silbentrennung ist ein integraler Bestandteil des Umbruchalgorithmus, beispielsweise weil vermieden werden soll, dass mehrere Trennungen in aufeinanderfolgenden Zeilen auftreten.
Die Silbentrennung wird im Publisher über die Sprache gesteuert und
musterbasiert vorgenommen (vielleicht sollte ich einen Beitrag dazu schreiben,
wie die Silbentrennung in TeX funktioniert…). Die Sprache kann man global
einstellen über <Options ...> oder Absatzweise.
Letzte Woche wurden Seitenzahlen in der Form »Seite x von y« dargestellt. Die aktuelle Seitenzahl wurde mit sd:current-page() ermittelt. Das funktioniert aber nur dann, wenn bekannt ist, wo man gerade ist. In einer Tabelle beispielsweise ist das Ergebnis das der Startseite. Folgendes Layout gibt 100 Mal die Zahl 1 aus:
Um die Länge des Dokuments in Seiten anzugeben, ist ein zweiter Durchlauf des Publishers
notwendig: Am Ende des ersten Durchlaufs wird die aktuelle (= letzte)
Seitennummer gespeichert, die man anschließend in den folgenden Durchläufen
nutzen kann.
Das folgende Beispiel erzeugt einige Seiten mit Ausgaben in der Form Seite 1 von ??. Das dient als Basis für die Ergänzungen.
Die letzten Tage hatte ich defekte ZIP-Dateien auf dem Server liegen. Das hat
sich dadurch geäußert, dass auf Mac und Linux das Programm sdluatex nicht
gestartet werden konnte. Die fehlerhaften ZIP-Dateien waren vermutlich zwei
Wochen lang online. Sorry!
Diese Woche gibt ein unscheinbares Feature: man kann mit sd:aspectratio(<Dateiname>) das Seitenverhältnis eines Bildes ermitteln. Das kann man sich zu nutze machen, wenn man eine Bilderstrecke so aufteilen möchte, dass alle Bilder mit derselben Höhe dargestellt werden. Die Breite der Bilder soll aber variabel sein. Ich zeige erst einmal, wie es aussehen könnte:
Nach recht kurzer (aber intensiver) Entwicklung gibt es nun ein neues »stable« Release: 2.6 Nachdem nun alle Bugs auf Github gefixt wurden, ist es Zeit diesen Stand einzufrieren.
[Nachtrag: es gibt zwar diverse Beiträge hier, die die Architektur von anderer Seite betrachten, formal gab es jedoch keine weitere Teile.]
In einer mehrteiligen Serie gebe ich einen Überblick über die Architektur des speedata Publishers. Hinweis: für »normale Anwender« ist diese Serie nicht gedacht, eher für Entwickler und Interessierte.
Ich fange mal direkt mit einem groben Schema an:
Grobe Übersicht über die Komponenten des speedata Publishers
Das Programm sp ist die Schnittstelle zum Benutzer. Es ist in der
Programmiersprache Go geschrieben und startet den
Prozess sdluatex oder luatex, je nach dem, was verfügbar ist. Bevorzugt
ist die erste Variante, damit kein Namenskonflikt mit einer eventuell
vorhandenen TeX-Installation verursacht wird. Außerdem wird ein
Verbindung auf einem Socket geöffnet und per Umgebungsvariable
(SP_SERVERPORT) übermittelt.
LuaTeX in der Version 0.79 wird gestartet. Die Datei sdini.lua wird
mit dem Prozess gestartet. Es wird die TeX-Bibliothek kpathsea
deaktiviert und durch eine eigene ersetzt, die callbacks dafür werden in
sd-callbacks.lua definiert.
Für die Kommunikation mit dem übergeordneten Prozess wird in comm.lua
eine TCP-Verbindung zum sp-Prozess gestartet. Derzeit wird diese Verbindung
genutzt, um Funktionalität von Go zu nutzen, speziell reguläre Ausdrücke für
die Funktionen contains(), replace() und tokenize() und für einen
robusten HTML Parser. In Zukunft wird vermutlich weitere Funktionalität im sp-
Prozess abgebildet. Die Kommunikation wird über ein sehr einfaches Protokoll
abgewickelt.
und
Bilder und Fonts werden über LuaTeX eingelesen. Die Fonts
werden mit der Bibliothek fontforge eingelesen. Die OpenType Tabellen werden
direkt in Lua-Tabellen abgebildet. Für die eingebundenen Bilder werden
Metadaten zur Verfügung gestellt.
LuaTeX erwartet in alter Tradition eine .tex-Datei. Die Datei publisher.tex besteht aus dem minimalen Code
um die Datei spinit.lua zu laden und dort (ganz zum Schluss) die main_loop() zu starten. Hier werden hauptsächlich ein paar Voreinstellungen gesetzt (z.B. die lccodes für die Silbentrennung), die Verbindung zum Go-Prozess erzeugt (siehe Punkt 3) und in der Datei
publisher.lua die Funktion dothings() aufgerufen, die wiederum die
XML-Dateien lädt und sonstige Initialisierung vornimmt. Interessant ist noch der nächste Punkt:
TeX, insbesondere LuaTeX, bietet einen sehr guten Absatzumbruchalgorithmus und andere Funktionalität, die im Publisher sehr nützlich sind. So kann man mit tex.linebreak() den Umbruch erzeugen und das Ergebnis verarbeiten. Mit tex.shipout() kann eine Seite in das PDF ausgegeben werden.
In der nächsten Folge gehe ich speziell auf die Datenstruktur ein, die LuaTeX intern nutzt.
Es gibt zwei Befehle, Text auszugeben: PlaceObject/Textblock und
Output/Text. Die erste Variante über Textblock erzeugt einen
rechteckigen Bereich, der nicht über mehrere Seiten umbrochen werden kann. Das
ist für Produktkataloge in der Regel ausreichend, für Fließtext aber nicht.
»Der Gestaltungsraster (in der Praxis oft das Gestaltungsraster), auch der
typografische Raster, Rastersystem oder auf Englisch auch Grid genannt, ist
ein Ordnungssystem in der visuellen Kommunikation, das als Hilfskonstruktion
die Organisation von grafischen Elementen auf einer Fläche oder in einem Raum
erleichtert. Gestaltungsaufgaben, in denen der Raster Anwendung findet, sind
meist typografischer Art – es wird dann von Rastertypografie gesprochen.«
Es handelt sich also um nicht sichtbare Linien oder Kästchen, an dem Objekte
ausgerichtet sind. Man kennt es beispielsweise vom Zeitungsdruck, wo es
oftmals fünf oder sechs Spalten gibt. Alle Bilder oder Anzeigen füllen dann
eine oder mehrere Spalten aus. Ebenso gibt es in Katalogen häufig
Rasterzeilen, die ähnlich funktionieren. Dadurch erreicht man ein klares
Layout.
Der speedata Publisher arbeitet grundsätzlich mit einem solchen Raster. Da
jede Publikation anders ist, gibt es keine Möglichkeit, eine sinnvolle Vorgabe
dafür zu machen. In der Voreinstellung ist das Raster mit einer Größe von 1cm
× 1cm gesetzt. Es gilt für die Seite sowie alle Positionierungsrahmen und
Gruppen. Anzeigen kann man das Raster mit sp --grid oder <Trace grid="yes"/> im Layout.
Diese Datei unter layout.xml speichern und die PDF-Datei mit sp --dummy erzeugen:
Wenn man genau hinschaut, sieht man, dass der erste und dann jeder fünfte
Strich etwas dunkler gezeichnet wird. Das hilft dabei, Rasterzellen zu zählen,
falls das notwendig sein sollte. Die rote Linie zeigt die Begrenzung der
Seite, in der Voreinstellung sind die Ränder jeweils 1cm. In dem Beispiel
sieht man auch schon, dass die Angaben bei row und column sich auf das
Raster bezieht, der Ursprung oben links hat die Koordinate 1,1. Bei row und
bei column kann man auch absolute Angaben machen wie 12cm. Das bezieht
sich dann immer auf die linke bzw. obere Entfernung zum Papierrand.
Das Raster wird mit dem Befehl <SetGrid> global eingestellt. Z.B.
<SetGridheight="12pt"nx="10"/>
setzt die Rasterhöhe auf 12 Punkt und die -breite auf 1/10 der Seitenbreite. Man kann auch noch Abstände zwischen den Rasterzellen festlegen.
Eine Schwierigkeit gibt es bei der Festlegung eines Rasterwerts auf eine bestimmte Größe: wenn die Papierbreite, der Seitenrand und die Rasterbreite festgelegt werden, können die Angaben sich widersprechen.
Wofür wird das Raster benötigt?
Ruft man sp mit der Option --show-gridallocation auf, so sieht man sofort,
wofür das Raster auch gut ist. Belegte Zellen werden intern markiert, so dass
kein weiteres Objekt in diesem Bereich platziert werden kann. Zumindest nicht
ohne Fehlermeldung oder dem Hinweis, dass kein Bereich dafür freigehalten
werden soll (allocate="no" in <PlaceObject>).
Lässt man die Angaben für Spalte und Zeile weg, sucht sich der Publisher die nächste freie Position selbsttätig.
Bilder, Barcodes, Boxen etc. haben feste Breiten und Höhen. Texte und Tabellen nutzen die noch vorhandene Breite meist aus. So benötigt die Textbox aus dem Beispiel oben keine Angabe einer Breite. Es wird einfach die Breite angenommen, die in Spalte 3 noch verfügbar ist, bei 10 Spalten Seitenbreite sind das 8 Spalten.
Benötigt ein Objekt (wie das Bild oben) eine Breiten- oder Höhenangabe, kann diese entweder absolut (z.B. 5cm) gegeben werden oder in Rasterzellen. Abstände zwischen den Rasterzellen werden automatisch berücksichtigt.
Eigene Raster in Gruppen
Es folgt ein Beispiel für ein Raster innerhalb einer Gruppe. Ohne die explizite <Grid .../>-Angabe wird das Raster der Seite genommen.
Ausschnitt aus einer Seite. Das Raster innerhalb der Gruppe ist deutlich feiner als das grobe Seitenraster.
Update 1.10.2016: die Option zum Anzeigen des Rasters ist nicht mehr unter Options zu finden, sondern unter Trace. Der Inhalt des Beitrags wurde angepasst. Siehe auch Feature der Woche: Debugging.
In der Serie »Feature der Woche« beschreibe ich jeden Montag mehr oder weniger nützliche Eigenschaften des Publishers. Kommentare gerne an mich per E-Mail oder einfach im Kommentarfeld.