CSS border / Radius und PDF
Ich bin ja gerade dabei, HTML und CSS-Fähigkeiten in den speedata Publisher einzubauen. Dazu gehören die großen Dinge wie Seitenvorlagen und Schriftarten, aber auch die kleinen Details, z.B. CSS Border. Die meist nur bei oberflächlicher Betrachtung einfach sind.
Einfache Fälle
Die HTML-Datei für die Beispiele ist einfach aufgebaut:
<!DOCTYPE html>
<head>
<link href="mystyle.css" rel="stylesheet">
</head>
<body>
<span>border</span>
</body>
</html>
mit der dazugehörigen CSS-Datei:
span {
border: 2px solid green;
}
Der erste »Aha-Effekt« kommt oft, wenn die Rahmen unterschiedliche Farben haben:
span {
border: 2px solid green;
border-right-color: yellow;
border-left-color: blue;
}
Rundungen
Noch ist die Konstruktion des Rahmens überschaubar.
Mit padding
erhöht sich der Abstand zwischen dem Inhalt der Box und dem farbigen Rahmen und mit margin
erhöht sich der Rand außerhalb des farbigen Rahmens.
Die CSS-Eigenschaften für den Rahmen (border
) können aber noch Angaben zum Radius beinhalten, diese geben die Krümmung des Außenradius an.
Ich gehe vom einfachen Fall aus, dass nur ein Radius angegeben wird, keine zwei (für die x- und für die y-Achse getrennt).
Krümmungen im Rahmen
Was passiert aber, wenn der Krümmungsradius größer ist, als die Strichdicke? Dann muss im Prinzip nur sichergestellt werden, dass die Rahmnendicke überall gegeben ist. Das hört sich einfach an, ist es aber nicht ganz. Folgenden Effekt gibt es, wenn unterschiedliche Rahmendicken benutzt werden:
span {
border: 1px solid green;
border-right-color: yellow;
border-top-right-radius: 9px;
border-right-width: 7px;
}
Die Konstruktion des inneren Radius ist, wenn man es einmal verstanden hat, doch recht einfach. Der innere Teil ist eine Ellipse, deren Radien die Differenz des Außenradius und der Strichdicke sind:
Ausgabe in PDF
Da mich aber immer die Ausgabe in PDF interessiert, stellt sich die Frage, wie ein ein solcher Rahmen als PDF-Anweisungen erzeugt werden kann.
PDF-Anweisungen sind so etwas wie »Move to position«, »Fill path« oder »Show text«. Also alles, was man im PDF sieht, wird durch solche Anweisungen ausgegeben. In der PDF-Sprache bestehen die Befehle meist aus ein oder zwei Buchstaben.
Die Anweisungen 0.5 w 0 0 m 20 0 l 10 10 l s
bedeuten zum Beispiel: setze die Liniendicke auf 0,5 (w
), gehe zu Position (0,0) (m
), ziehe eine Linie zu (20,0) (l
), dann zu (10,0) und schließe die Linie und zeichne den nun entstandenen Pfad mit einem Strich (s
). Das Ergebnis ist
Die Zeichnungen in PDF wird immer über solche Pfade realisiert, die auch gefüllt werden oder als »Ausschneidepfad« dienen können. Krümmungen werden über Bézierkurven dargestellt. Mein Vorgehen ist nun, über den farbigen Rahmen zwei Pfade zu legen, deren Äußeres und Inneres weggeschnitten werden:
Die farbige Rahmen
Der Code für die vier Trapeze ist noch übersichtlich (das %
-Zeichen ist ein Kommentar):
q
0 w
% Trapez 1
0 0.502 0 rg 0 0.502 0 RG
8 3 m 24.9 3 l 32.9 11 l 0 11 l b
% Trapez 2
1 1 0 rg 1 1 0 RG
24.9 3 m 32.9 -5 l 32.9 11 l 24.9 3 l b
% Trapez 3
0 0.502 0 rg 0 0.502 0 RG
0 -5 m 32.9 -5 l 24.9 3 l 8 3 l b
% Trapez 4
0 0 1 rg 0 0 1 RG
0 -5 m 8 3 l 8 3 l 0 11 l b
Q
q
und Q
rahmen den Code ein, mit w
wird die Liniendicke auf 0 gesetzt, die erste Zeile in jedem Trapez (… rg
, … RG
) setzen die Farbe, die anderen Befehle zeichnen die Linien (l
) und beenden den Pfad und füllen die Fläche (b
). Jede Koordinate besteht aus zwei Zahlen (x- und y-Wert).
Die »Ausschneidepfade«
4 -5 m
28.9 -5 l
31.107 -5 32.9 -3.208 32.9 -1 c
32.9 7 l 32.9 9.208 31.107 11 28.9 11 c
4 11 l
1.792 11 0 9.208 0 7 c
0 -1 l
0 -3.208 1.792 -5 4 -5 c
4 -3 m
28.9 -3 l
30.004 -3 30.9 -2.104 30.9 -1 c
30.9 7 l
30.9 8.104 30.004 9 28.9 9 c
4 9 l
2.896 9 2 8.104 2 7 c
2 -1 l
2 -2.104 2.896 -3 4 -3 c
h W* n
Es gibt hier zwei Pfade (außen und innen), die aus 16 Punkten bestehen:
Die Punkte 3, 4, 7, 8, 11, 12 und 15,16 sind die Hilfspunkte für die Bézierkurven, die bei dem c
-Befehl angegeben werden. Hier ist noch einmal der äußere Pfad mit Kommentaren:
% Punkt 1
4 -5 m
% Punkt 2
28.9 -5 l
% Punkte 3, 4 und 5
31.107 -5 32.9 -3.208 32.9 -1 c
% Punkte 6, 7 und 8
32.9 7 l 32.9 9.208 31.107 11 28.9 11 c
% Punkt 9
4 11 l
% Punkte 10, 11 und 12
1.792 11 0 9.208 0 7 c
% Punkt 13
0 -1 l
% Punkte 14, 15 und 16
0 -3.208 1.792 -5 4 -5 c
Nachdem die beiden Pfade erstellt wurden, werden die drei Befehle h W* n
ausgeführt. Dadurch wird der Pfad geschlossen (h
), als Ausschneidepfad definiert (W*
) und beendet, ohne den Pfad zu zeichnen oder zu füllen (n
).
Und LuaTeX?
Die Ausgabe mit LuaTeX ist recht einfach. Es wird ein sog. Whatsit erzeugt mit dem Untertyp pdf_literal und in den Ausgabestrom eingefügt. Die beiden langen PDF-Befehlsketten von oben werden dafür aneinander gehängt.
local n_clip = node.new("whatsit","pdf_literal")
-- Zeichenkette der Ausschneidepfade wie oben
-- und angehängt (in Lua mit zwei Punkten: ..)
-- Zeichenkette mit PDF-Befehlen für die Trapeze wie oben
n_clip.data = "4 -5 m ... h W* n " .. "q 0 w ... Q"