PDFs können ein Inhaltsverzeichnis enthalten, welches vom Anzeigeprogramm neben dem eigentlichen Dokument als Liste oder Baumstruktur angezeigt wird. Typisch ist ein Balken links neben der Dokumentansicht. Durch Anklicken der einzelnen Einträge springt das Programm an die entsprechende Stelle. Vor allem in grossen Dokumenten ist dies äusserst nützlich.
Ebenfalls können im Dokument Links gesetzt werden. Hierbei handelt es sich um Regionen (meist Textstellen), die angeklickt werden können, worauf die Ansicht an den verlinkten Punkt springt. Falls man im Dokument Seiten mit Verzeichnissen und Indexen hat, so gilt es als guter Stil, die einzelnen Einträge mit den entsprechenden Stellen im Dokument zu verlinken.
Und wo wir sowieso schon beim Thema sind: Ein Link kann nicht nur auf eine Stelle im Dokument verweisen, sondern auch auf eine Webseite.
Sowohl für Einträge des Inhaltsverzeichnisses wie auch für interne Links muss angegeben werden, wohin beim Anklicken gesprungen werden soll. Anders als etwa bei HTML ist so ein Sprungziel aber nicht eine bestimmte Stelle im Dokument, sondern eine bestimmte Ansicht des Dokuments.
In seiner generellen Form wird ein Sprungziel als Array mit 5 Elementen umschrieben, und sieht wie folgt aus:
[seite /XYZ x y z]
Dabei steht seite für eine Referenz auf das Seitenobjekt der Seite, auf die gesprungen werden soll. x und y sind die Koordinaten der linken, oberen Ecke des sichtbaren Bereichs, und z ist der Zoomfaktor. Ein Faktor von 1 steht dabei für 100%. Ein Faktor von 0 oder null
bedeutet, dass die vor dem Klick gesetzte Zoomstufe beibehalten werden soll.
Alternativ kann man das Sprungziel auch so formulieren, dass die Zoomstufe automatisch angepasst wird.
[seite /FitH y]
Dies passt die Zoomstufe so an, dass gerade die ganze Breite der Seite sichtbar ist. Dementsprechen muss nur noch die Seite und die y-Koordinate des oberen Rands des sichtbaren Bereichs angegeben werden.
[seite /Fit]
Hiermit schliesslich wird die Zoomstufe so angepasst, dass die ganze Seite auf einmal sichtbar ist. Folglich muss nur noch die Seite selbst angegeben werden. In den meisten Fällen ist die Darstellung so aber zu klein, um die Seite zu lesen.
Beispiel:
[10 0 R /XYZ 60 720 null]
Dies springt auf die Seite im Seitenobjekt 10, belässt die Zoomstufe, und scrollt das Dokument so, dass der Punkt [60 720] in der linken, oberen Ecke des Ausschnitts ist.
Das Inhaltsverzeichnis besteht aus einer Liste von Verzeichniselementen. Jedes Element hat einen Text und ein Sprungziel. Zudem kann jedes der Elemente wiederum eine Liste von Unterelementen haben. Für die Unterelemente gelten dabei die gleichen Regeln. Folglich können auch sie wiederum Unterelemente haben.
In der PDF Datei ist dies so organisiert, dass vom Katalogobjekt auf ein Verzeichnisobjekt verwiesen wird. Dieses verweist auf eine Gruppe von Verzeichniselementobjekten. Jedes Elementobjekt steht für einen Verzeichniseintrag, und kann wiederum auf eine Gruppe von Elementobjekten verweisen, welche Untereinträge zu diesem Verzeichniseintrag enthalten.
Das Katalogobjekt kennen wir schon. Es erhält einen neuen Eintrag /Outlines
mit einer Referenz auf das Verzeichnisobjekt.
Das Verzeichnisobjekt ist ein Dictionary mit folgenden Einträgen:
/Type | immer /Outlines |
---|---|
/First | Referenz auf das erste Element der obersten Gruppe |
/Last | Referenz auf das letzte Element der obersten Gruppe |
/Count | Anzahl der Elemente |
/First
und /Last
beziehen sich nur auf die Elementgruppe, welche die oberste Hierarchiestufe bildet. /Count
hingegen ist die Anzahl sämtlicher Elemente, einschliesslich aller Unterelemente.
Die Elementobjekte sind ebenfalls Dictionaries. Diese haben grundsätzlich folgende Einträge:
/Title | Text des Eintrags |
---|---|
/Dest | Sprungziel |
/Parent | Referenz auf das übergeordnete Element |
/Prev | Referenz auf das vorhergehende Element |
/Next | Referenz auf das nächste Element |
/Title
ist ein String, der im Verzeichnis angezeigt werden soll.
/Dest
ist ein normales, internes Sprungziel.
/Parent
ist eine Referenz auf das übergeordnete Elementobjekt bzw. auf das Verzeichnisobjekt.
/Prev
und /Next
beziehen sich auf das vorhergehende bzw. nachfolgende Element der Gruppe, zu der das Element gehört. Beim ersten Eintrag der Gruppe wird daher /Prev
weggelassen. Beim letzten Eintrag der Gruppe wird /Next
weggelassen. Besteht die Gruppe nur aus einem Eintrag, wird beides weggelassen.
Elemente mit Unterelementen haben im Dictionary drei weitere Einträge:
/First | Referenz auf das erste Element der Untergruppe |
---|---|
/Last | Referenz auf das letzte Element der Untergruppe |
/Count | Anzahl der Unterelemente |
Die drei Einträge funktionieren ähnlich, wie im Verzeichnisobjekt. /First
und /Last
beziehen sich nur auf die Gruppe der Unterelemente dieses Eintrags auf der nächsten Hierarchiestufe, wohingegen für /Count
auch allfällige Unterelemente der Unterelemente berücksichtigt werden müssen.
Beispiel:
1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 9 0 R >> endobj 2 0 obj << /Type /Outlines /First 3 0 R /Last 8 0 R /Count 6 >> endobj 3 0 obj << /Title (1 erstes Kapitel) /Dest [15 0 R /XYZ 60 782 0] /Parent 2 0 R /Next 4 0 R >> endobj 4 0 obj << /Title (2 zweites Kapitel) /Dest [17 0 R /XYZ 60 782 0] /Parent 2 0 R /Prev 3 0 R /Next 8 0 R /First 5 0 R /Last 6 0 R /Count 3 >> endobj 5 0 obj << /Title (2.1 erster Teil) /Dest [17 0 R /XYZ 60 782 0] /Parent 4 0 R /Next 6 0 R >> endobj 6 0 obj << /Title (2.2 zweiter Teil) /Dest [19 0 R /XYZ 60 782 0] /Parent 4 0 R /Prev 5 0 R /First 7 0 R /Last 7 0 R /Count 1 >> endobj 7 0 obj << /Title (2.2.1 Unterabschnitt) /Dest [19 0 R /XYZ 60 421 0] /Parent 6 0 R >> endobj 8 0 obj << /Title (3 drittes Kapitel) /Dest [21 0 R /XYZ 60 782 0] /Parent 2 0 R /Prev 4 0 R >> endobj
Normalerweise ist das Verzeichnis komplett ausgeklappt. Das heisst, alle Unterelemente sind von Anfang an sichtbar. Man kann aber auch die Unterelemente verstecken. Sie sind dann bei Bedarf einblendbar. Hierfür muss man die /Count
Einträge anders befüllen.
Im Verzeichnisobjekt wird /Count
auf die Anzahl von Anfang an sichtbarer Elemente gesetzt.
Ähnliches gilt für Oberelemente, die weiterhin von Anfang an ausgeklappt sein sollen: Ihr /Count
Eintrag wird auf die Anzahl von Anfang an sichtbarer Unterelemente gesetzt.
Bei Oberelementen, die zunächst eingeklappt sein sollen, setzt man /Count
auf die negierte Anzahl Unterelemente, die beim ersten Ausklappen sichtbar werden.
Um also zum Beispiel alles anfangs eingeklappt zu haben, setzt man den /Count
Eintrag des Verzeichnisobjekts auf die Anzahl Elemente der obersten Hierarchiestufe, und die /Count
Einträge der Oberelemente auf die negierte Anzahl der direkten Unterelemente.
Links sind grundsätzlich anklickbare Flächen innerhalb einer Seite. Sie werden durch einen Rahmen gekennzeichnet, und haben einen Anklickeffekt. Bei Links innerhalb eines Textes ist es allerdings üblich, dem Rahmen eine Dicke von 0 zu geben (was ihn verschwinden lässt). Will man die Textstelle speziell eingefärbt haben, wie dies bei Webseiten üblich ist, so geht dies leider nicht automatisch. Die Farbe muss im Textsatz explizit umgestellt werden.
Für jeden Link brauchen wir ein indirektes Objekt. Diese werden dann vom Seitenobjekt der Seite, welche die Links enthalten soll, referenziert.
Das Seitenobjekt erhält einen zusätzlichen Dictionaryeintrag /Annots
. Als Wert hat dieser Eintrag ein Array mit Referenzen auf die Linkobjekte.
Es handelt sich um ein Dictionary mit folgenden Einträgen:
/Type | immer /Annot |
---|---|
/Subtype | immer /Link |
/Rect | anklickbarer Bereich |
/Dest | internes Sprungziel |
/A | externes Sprungziel |
/Border | Rahmentyp |
/H | Effekttyp |
/Rect
hat als Wert ein Array mit vier Zahlen, welche nacheinander die X- und Y-Koordinate der linken, unteren Ecke, und die X- und Y-Koordinate der rechten, oberen Ecke des anklickbaren Bereichs enthalten.
/Dest
wird nur bei internen Links angegeben. Der Wert ist ein normales Sprungziel.
/A
wird nur bei Weblinks angegeben. Es hat als Wert ein Dictionary mit zwei Einträgen:
/S | immer /URI |
---|---|
/URI | Die URL des Sprungziels |
Die URL muss dabei als String angegeben werden. Es wird die komplette URL einschliesslich Protokoll („http://“ etc.) benötigt.
/Border
definiert, wie (ob) der Rahmen um den Link gezeichnet werden soll. Wird der Eintrag weggelassen, so wird ein 1pt breiter, durchgezogener Rahmen mit nicht abgerundeten Ecken gezeichnet.
Als Wert wird ein Array mit drei Zahlen erwartet. Die Bedeutung der einzelnen Einträge ist:
Allerdings scheinen praktisch alle Programme die Parameter für Eckabrundung zu ignorieren. Optional kann als vierter Eintrag ein Array mit einem Strichmuster angegeben werden.
/H
definiert den Anklickeffekt. Wird der Eintrag weggelassen, so wird der /I
Effekt verwendet. Die möglichen Effekte sind:
/N | kein Effekt |
---|---|
/I | der anklickbare Bereich wird invertiert |
/O | der Rahmen des anklickbaren Bereichs wird invertiert |
/P | der anklickbare Bereich wird „eingedrückt“ |
Beispiel:
14 0 obj << /Type /Page /Parent 9 0 R /Annots [15 0 R 16 0 R] /Contents 17 0 R >> endobj 15 0 obj << /Type /Annot /Subtype /Link /Rect [72 700 172 712] /Dest [18 0 R /XYZ 60 782 0] >> endobj 16 0 obj << /Type /Annot /Subtype /Link /Rect [72 500 172 512] /A << /S /URI /URI (http://www.irgendwo.example/) >> /Border [0 0 0] >> endobj
Diskussion