PDF/A und Barrierefreiheit

Das Unangenehme an PDF/A ist, dass Konformität völlig unsichtbar bleibt. Dasselbe LaTeX-Dokument liefert ein optisch identisches PDF, das als A-2b besteht und als A-1b durchfällt – und führt man die Prüfung wirklich aus, nennt der Validator den Grund in einer Zeile: Ein ExtGState-Wörterbuch trägt einen ca-Schlüssel mit 0.5 statt 1.0. PDF/A handelt nicht von schönen PDFs, sondern ist eine ISO-Anforderung an die Struktur im Inneren der Datei. Diese Seite behandelt, was der Standard tatsächlich verlangt, die zwei Wege aus LaTeX heraus (pdfx und \DocumentMetadata) und den meist übersprungenen Schritt: wie sich feststellen lässt, ob die erzeugte Datei wirklich konform ist.

Was PDF/A tatsächlich verlangt

PDF/A (ISO 19005) ist ein Archivstandard, und im Kern verlangt er eines: Die Datei muss vollständig in sich geschlossen sein. Wer sie in zehn Jahren öffnet, hat weder die Schriften noch die Farbmanagement-Einstellungen noch irgendeine andere Datei – und trotzdem muss sie korrekt lesbar sein. Daraus folgt jede einzelne konkrete Bedingung. Schriften vollständig einbetten (nie darauf bauen, was beim Lesenden installiert ist). Keine Verschlüsselung (ein verlorener Schlüssel bedeutet ein verlorenes Dokument). XMP-Metadaten (Titel und Autor als standardisiertes XML im PDF selbst). Ein eingebetteter Output Intent, also ein ICC-Profil (damit „dieses Rot“ seine Farbraumdefinition mitbringt). Nach derselben Logik ist alles verdächtig, was über die Datei hinausgreift, etwa das Ziel eines Formularversands.

PDF/A mit pdfx erzeugen – das ICC-Profil liegt bei

Eine Zeile \usepackage[a-2b]{pdfx} und eine Datei \jobname.xmpdata mit Titel und Autor genügen. Ein ICC-Profil muss nicht selbst beschafft werden. Früher hieß es, das sRGB-Profil sei von Adobes Website zu holen; in TeX Live 2024 liefert das Paket colorprofiles eines mit, und das Log hält die Einbettung als <<sRGB.icc>> fest. Im selben Log bestätigt ** pdfx: Metadata file document.xmpdata read successfully., dass die Metadaten gelesen wurden; fehlt die Datei, erscheint stattdessen ** pdfx: No file document.xmpdata . Metadata will be incomplete! – wobei, wie sich zeigen wird, auch bei ignorierter Warnung eine Datei herauskommt, die die Prüfung besteht. Neben a-1b, a-2b und a-3b bietet das Paket die Barrierefreiheitsstufen a-1a, a-2a, a-3a sowie die Unicode-Stufen a-2u, a-3u. Die drucknahen PDF/X-Varianten (x-1a und Verwandte) stammen aus demselben Paket.

latex
% document.tex
\documentclass{article}
\usepackage[a-2b]{pdfx}   % reads document.xmpdata, embeds sRGB.icc
\begin{document}
Hello PDF/A.
\end{document}

% document.xmpdata -- a separate file, same base name
\Title{A Test Document}
\Author{Test Author}
\Keywords{LaTeX\sep PDF/A}

A-1b, A-2b und A-4: ob Transparenz durchkommt

Die Zahl bezeichnet die zugrunde liegende PDF-Version, der Buchstabe am Ende die Strenge. A-1 baut auf PDF 1.4, A-2 auf PDF 1.7, A-3 ist A-2 mit erlaubten Anhängen, A-4 baut auf PDF 2.0. Das abschließende b steht für basic – das Erscheinungsbild muss reproduzierbar sein, mehr nicht. a steht für accessible und ergänzt Tagging, also die logische Struktur. u verlangt, dass sich der Text auf Unicode abbilden lässt. Praktisch am schmerzhaftesten ist der Unterschied bei Transparenz. Ein Dokument mit zwei TikZ-Rechtecken bei opacity=0.5, gebaut mit [a-1b]{pdfx} und durch veraPDF geschickt, fällt bei ISO 19005-1:2005 Klausel 6.4 durch, Begründung: „An ExtGState dictionary contains the ca key (fill alpha) with value 0.5 other than 1.0“. Nur die Option auf [a-2b] geändert – und es besteht. Eine zwanzig Jahre alte Tatsache, dass PDF 1.4 keine Transparenz kennt, bestimmt bis heute, was ein Repositorium annimmt.

StufeBasis-PDFKernpunkt
A-1bPDF 1.4Am engsten. Keine Transparenz – jede Grafik mit opacity fällt durch. Objektströme sind ebenfalls verboten
A-2bPDF 1.7Transparenz besteht. Aus LaTeX heraus die Standardwahl. Auch JPEG 2000 ist erlaubt
A-3bPDF 1.7A-2b zuzüglich beliebiger Dateianhänge. Gefordert, wenn Rohdaten im Dokument mitreisen sollen
A-4PDF 2.0Das Neueste. Der Header muss %PDF-2.0 lauten, daher ist pdfversion=2.0 nötig. Aus pdfx nicht verfügbar; \DocumentMetadata verwenden

Der Weg über \DocumentMetadata – ohne passende pdfversion fällt es durch

Der andere Weg ist \DocumentMetadata{pdfstandard=A-2b}, vor \documentclass gesetzt. Er lädt kein Paket und akzeptiert alles von A-1B bis A-4 – so aufgeschrieben besteht allerdings nur A-2b. pdfTeX schreibt standardmäßig PDF 1.5; für A-1b wird das zurückgewiesen, weil die Querverweistabelle ein Stream ist (The document uses xref streams, Klausel 6.1.4), für A-4, weil „File header %PDF-1.5 ... does not match the pattern %PDF-2.n“ (Klausel 6.1.2). Die Lösung steckt in denselben Klammern: mit pdfversion=1.4 besteht A-1b, mit pdfversion=2.0 besteht A-4. Ergänzt man A-2b umgekehrt um pdfversion=2.0, fällt es mit „%PDF-2.0 ... does not match the pattern %PDF-1.n“ durch – denn A-2 ist auf PDF 1.7 definiert, nicht höher. Jeder Standard hat eine andere richtige Antwort, und genau dort wird es falsch gemacht.

AngabeBeim Standard belassen (PDF 1.5)Mit ergänzter pdfversion
pdfstandard=A-1bFällt durch – Klausel 6.1.4, „uses xref streams“Mit pdfversion=1.4 besteht es
pdfstandard=A-2bBesteht – die einzige Kombination, die nichts brauchtMit pdfversion=2.0 fällt es durch (Klausel 6.1.2)
pdfstandard=A-4Fällt durch – Klausel 6.1.2, „header %PDF-1.5“Mit pdfversion=2.0 besteht es

Warum besteht pdfx mit a-1b dann, obwohl weiterhin ein PDF-1.5-Header geschrieben wird? Die Antwort steht im Paketquelltext. Zeile 515 von pdfx.sty trägt den Kommentar „PDF/A-1b doesn't allow object compression“, und unmittelbar danach wird \pdfobjcompresslevel=0 gesetzt. Statt über die Zahl im Header zu streiten, wird die vom Standard verbotene Funktion einfach nicht benutzt. Darin liegt der Charakterunterschied der beiden Wege. pdfx ist ein Paket, das die Ausgabe so lange zurechtbiegt, bis sie zum Standard passt; \DocumentMetadata ist ein Kernel-Mechanismus, der erklärt, welcher Standard beansprucht wird – und es bleibt einem selbst überlassen, den Inhalt diesem Anspruch anzupassen. Der zweite Unterschied betrifft die Metadaten: pdfx liest .xmpdata automatisch, \DocumentMetadata trägt weder Titel noch Autor von sich aus ein. Beides setzt man selbst mit \hypersetup{pdftitle=...} und Verwandten (siehe die Seite zu Lesezeichen und Metadaten).

latex
% before \documentclass -- the version must match the standard
\DocumentMetadata{
  pdfstandard = A-4,
  pdfversion  = 2.0,   % A-4 needs a %PDF-2.0 header
  lang        = en
}
\documentclass{article}

% for A-1b it is pdfversion = 1.4 instead;
% for A-2b, leave pdfversion out entirely.

Das Ergebnis prüfen: veraPDF – und was ein Bestehen nicht bedeutet

Von der LaTeX-Seite aus lässt sich nicht feststellen, ob die Datei konform ist. Das Log sagt nur, dass PDF/A-Ausgabe angefordert wurde; ob das Ergebnis den Standard wirklich erfüllt, ist eine andere Frage. Dieses Urteil fällt ein PDF/A-Validator, und der De-facto-Standard ist veraPDF, der quelloffene Referenzprüfer. Er gehört nicht zu TeX Live und muss separat installiert werden. Die Anwendung ist schlicht: verapdf file.pdf liest den XMP-Bezeichner im PDF, bestimmt daraus die zu prüfende Stufe und antwortet in einer Zeile mit PASS ... 2b oder FAIL ... 1b. Mit -f 1b lässt sich eine Stufe erzwingen. Bei einem Fehlschlag zählt die Klauselnummer: 6.4 (Transparenz), 6.1.2 (Header-Version), 6.3.3 (Erscheinungsbild von Annotationen) zeigen unmittelbar, was zu ändern ist.

shell
# auto-detect the level from the file itself
verapdf document.pdf
# -> PASS /path/document.pdf 2b

# force a level (useful to see what a stricter one would say)
verapdf -f 1b --format text document.pdf
# -> FAIL /path/document.pdf 1b

# the XML report names the clause and the exact reason
verapdf -f 1b document.pdf > report.xml

Eine Tatsache erspart hier späteres Bedauern: Ein bestandener Test bedeutet nicht, dass die Metadaten in Ordnung sind. Wird die .xmpdata-Datei vergessen und die Warnung ** pdfx: No file ... Metadata will be incomplete! einfach stehen gelassen, antwortet veraPDF auf das Ergebnis mit PASS ... 1b – ohne Titel und ohne Autor in der Datei. Konformitätsstufe b verlangt, dass XMP-Metadaten strukturell korrekt vorhanden sind, nicht dass sie ausgefüllt sind. Genau die leeren Felder bereiten Bibliotheken und Repositorien Ärger; ein bestandener Validator und eine fertige Abgabe sind daher zweierlei. Ebenso lohnt die Gewohnheit, die Schrifteinbettung mit pdffonts zu kontrollieren (ausführlich auf der Seite zur PDF-Erzeugung).

Interaktive Formulare und PDF/A vertragen sich nicht

Ein einziges Eingabefeld aus der Form-Umgebung von hyperref genügt, damit die PDF/A-Prüfung durchfällt. Ein Dokument mit nur einem \TextField, gebaut mit [a-2b]{pdfx} und durch veraPDF geschickt, scheitert an Klausel 6.3.3: „An annotation does not contain an appearance dictionary“. hyperref überlässt das Zeichnen des Feldes dem Viewer – genau das bedeutet NeedAppearances –, während PDF/A verlangt, dass das Erscheinungsbild fest in der Datei steht. Kommt ein Submit-Knopf hinzu, mehren sich die Verstöße um Klausel 6.4.1, „A Widget annotation dictionary shall not contain the A or AA keys“ – einem Formularelement überhaupt eine Aktion mitzugeben, ist verboten. Bei näherem Hinsehen ist das folgerichtig: Ein Archivstandard kann kein Bedienelement segnen, dessen Aufgabe die Kommunikation nach außen ist. Verlangt eine Abgabestelle beides, PDF/A und ein ausfüllbares Formular, widersprechen sich die Anforderungen – also vorher nachfragen.

Getaggtes PDF und PDF/UA: Barrierefreiheit ist noch in Bewegung

Das von den a-Stufen verlangte Tagging bedeutet, die logische Struktur – Überschriften, Absätze, Listen, Lesereihenfolge, Alternativtexte – ins PDF einzubetten, damit ein Screenreader das Dokument durchlaufen kann. Der eigenständige Barrierefreiheitsstandard ist PDF/UA (ISO 14289), dessen zweiter Teil PDF/UA-2 heißt. Auf LaTeX-Seite ist die Umsetzung das Paket tagpdf des LaTeX Project (Ulrike Fischer); die Fassung in TeX Live 2024 trägt Version 0.98x vom 2024-02-29 – eine Versionsnummer, die mit Null beginnt, sagt alles. Die Low-Level-Befehle zum Setzen von Tags von Hand, etwa \tagstructbegin, stammen aus diesem Paket. Tatsächlich erzeugt \DocumentMetadata{tagging=on} auf dem Kernel von TeX Live 2024 (LaTeX2e 2023-11-01) die Meldung ! LaTeX Error: The key 'document/metadata/tagging' is unknown and is being ignored. In dieser Fassung lautet der Schalter testphase=phase-III, womit pdfinfo tatsächlich Tagged: yes meldet. Wie der Name sagt, handelt es sich um eine Testphase-Funktion, die Schreibweise wird sich ändern. Vor dem Einsatz die aktuelle Dokumentation prüfen.

Und eines gehört ehrlich vermerkt: Beides zugleich zu erfüllen ist noch nicht leicht. Ein Dokument, das mit pdfstandard=A-2b allein besteht, fiel nach Ergänzung von testphase=phase-III bei veraPDF an Klausel 6.2.11.5 durch: „Glyph width 333 in the embedded font program is not consistent with the Widths entry of the font dictionary (value 334.2)“. Das ist kein Mangel der Tag-Struktur, sondern eine Abweichung bei den Glyphenbreiten der eingebetteten Schrift. Wird ein getaggtes PDF/A verlangt, vor dem Versand veraPDF laufen lassen – wer annimmt, es werde schon klappen, steht in der Nacht vor der Abgabe fest.

Was vor der Abgabe zu tun ist

  • Zuerst nach der Stufe fragen. Heißt es nur „PDF/A“, klären, ob A-1b oder A-2b gemeint ist. Sobald Transparenz in den Abbildungen steckt, entscheidet dieser Unterschied über die Annahme.
  • Im Zweifel pdfx mit a-2b. \usepackage[a-2b]{pdfx} und Titel sowie Autor in \jobname.xmpdata. Die einzige Kombination, die ohne Zusätze besteht.
  • Wird A-4 verlangt, \DocumentMetadata{pdfstandard=A-4,pdfversion=2.0} verwenden. pdfx endet bei A-3 und kann A-4 nicht erzeugen.
  • Die .xmpdata nicht vergessen. Die Prüfung besteht auch ohne sie, also selbst im Log nach der Warnung Metadata will be incomplete! suchen.
  • Vor dem Versand jedes Mal einmal verapdf document.pdf laufen lassen. Es liegt TeX Live nicht bei und muss separat installiert werden. Bei einem Fehlschlag die Klauselnummer lesen (6.4, 6.1.2, 6.3.3).
  • Auf Formulare verzichten. Ein Dokument mit ausfüllbaren Feldern wird PDF/A nicht erfüllen.