Schriften in PDF-Dokumenten sind keine einfach Sache, spielen aber spätestens dann eine Rolle, wenn eine verwendete Schriftarten nicht mehr zu den durch den PDF-Standard definierten 14 Schriften gehört. Auch für die Archivierung von PDF-Dokumenten spielen Schriften eine besondere Rolle. PDFUnit bietet rund um das Thema „Schriften“ unterschiedliche Tags an:
<!-- Tags to test fonts: --> <hasNumberOfFonts identifiedBy=".." (Filters are explained later) /> <hasFonts ofThisTypeOnly=".."> (Either this attribute, <matchingXPath /> or one of the <matchingXML /> nested elements.) </hasFonts> <hasFont withNameContaining=".." (One of this two withNameNotContaining=".." attributes is required) />
Was ist eine „Schrift“? Soll ein „Subset“ einer Schrift als eigene Schrift gezählt werden? Für Softwareentwickler sind diese Fragen selten relevant, für ein Testwerkzeug schon. Da es das Ziel eines Unittests ist, beim zweiten Aufruf dasselbe Ergebnis zu liefern, wie beim ersten Aufruf, ist es eigentlich egal, wie gezählt wird. Da alle PDF-Werkzeuge die Frage entscheiden müssen, was sie zählen, liefern sie auch unterschiedliche Werte für die Anzahl von Schriften.
In PDFUnit gelten zwei Schrift als „equals“, wenn die
für einen Test relevanten Vergleichskriterien gleiche Werte haben.
Die Vergleichskriterien werden mit dem Attribut identifiedBy=".."
angegeben:
<!-- Constants to identify fonts: -->
identifiedBy="ALLPROPERTIES"
identifiedBy="BASENAME"
identifiedBy="BASENAME_ENCODING"
identifiedBy="BASENAME_ENCODING_ENCODINGDIFF"
identifiedBy="CONVERTIBLE2UNICODE"
identifiedBy="EMBEDDED"
identifiedBy="EMBEDDED_CONVERTIBLE2UNICODE"
identifiedBy="NAME"
identifiedBy="NAME_TYPE"
identifiedBy="TYPE"
Die folgende Liste erläutert die Vergleichskriterien für Schriften:
Konstante | Beschreibung |
---|---|
ALLPROPERTIES
| Alle Eigenschaften eines Fonts gelten als identifizierend. Von zwei verwendeten Schriften, die in allen Eigenschaften gleichwertig sind, wird nur eine gezählt. |
BASENAME
| Es werden nur die unterschiedlichen Basisschriften gezählt. |
BASENAME_ENCODING
| Der Name der Basisschrift und das Encoding werden gemeinsam als Unterscheidungsmerkmal benutzt. |
BASENAME_ENCODING_ENCODINGDIFF
|
Zusätzlich zur vorhergehenden Identifizierung müssen zwei Schriften auch noch
einen unterschiedlichen Wert in der Eigenschaft Encoding-Differenz besitzen.
Die „Encoding-Differenz“ ist der Wert des PDF-Objektes mit
dem Namen /Differences .
|
CONVERTIBLE2UNICODE
| Dieser Filter zählt nur solche Schriften, die in Unicode konvertiert werden können. |
EMBEDDED
| Mit diesem Filter werden sämtliche Schriften erfasst, die eingebettet sind. |
EMBEDDED_CONVERTIBLE2UNICODE
| Zusätzlich zu dem vorhergehenden Filter gilt hier noch die Eigenschaft, nach Unicode konvertierbar zu sein, als Unterscheidungsmerkmal. |
NAME
| Es werden Schriften mit unterschiedlichem Name gezählt. |
NAME_TYPE
| Die Kombination von Name und Typ einer Schrift gelten als identifizierender Teil. |
TYPE
| Es werden nur Schriften gezählt, die einen unterschiedlichen Typ haben. |
Hier ein Beispiel, das die verschiedenen Vergleichskriterien benutzt:
<testcase name="hasNumberOfFonts_Japanese"> <assertThat testDocument="fonts/fonts_11_japanese.pdf"> <hasNumberOfFonts identifiedBy="ALLPROPERTIES">65</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="BASENAME">9</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="BASENAME_ENCODING">16</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="BASENAME_ENCODING_ENCODINGDIFF">16</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="CONVERTIBLE2UNICODE">46</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="EMBEDDED">6</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="EMBEDDED_CONVERTIBLE2UNICODE">0</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="NAME">50</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="NAME_TYPE">55</hasNumberOfFonts> <hasNumberOfFonts identifiedBy="TYPE">3</hasNumberOfFonts> </assertThat> </testcase>
Test, die auf die Namen von Schriften zielen, sind einfach:
<testcase name="hasFont_WithNameContaining"> <assertThat testDocument="fonts/fonts_15_openoffice.pdf"> <hasFont withNameContaining="Arial" /> </assertThat> </testcase>
Schriftnamen innerhalb eines PDF-Dokumentes enthalten gelegentlich noch ein
Präfix, z.B. FGNNPL+ArialMT
. Weil dieses Präfix für Tests uninteressant
ist, prüft PDFUnit lediglich, ob der gesuchte Schriftname in den
Schriftnamen des PDF-Dokumentes als Teilstring enthalten ist.
In einem Test können mehrere Schriftnamen getestet werden:
<testcase name="hasHasFont_MultipleNames"> <assertThat testDocument="fonts/fonts_15_openoffice.pdf"> <hasFont withNameContaining="Arial" /> <hasFont withNameContaining="Georgia" /> <hasFont withNameContaining="Tahoma" /> <hasFont withNameContaining="TimesNewRoman" /> <hasFont withNameContaining="Verdana" /> <hasFont withNameContaining="Verdana-BoldItalic" /> </assertThat> </testcase>
Weil es gelegentlich interessant ist, zu wissen, dass eine bestimmte Schriftart in einem Dokument nicht enthalten ist, gibt es auch hierfür einen passenden Test:
<testcase name="hasFontWithName_NotContaining"> <assertThat testDocument="fonts/fonts_15_openoffice.pdf"> <hasFont withNameNotContaining="ComicSansMS" /> </assertThat> </testcase>
Komplexere Tests auf Schriftnamen können mit XPath-Ausdrücken realisiert werden. Sie werden weiter unten in diesem Kapitel beschrieben.
Sie können prüfen, ob alle in einem PDF-Dokument verwendeten Schrifttypen einem bestimmten Typ entsprechen:
<testcase name="hasFonts_OfThisTypeOnly_TrueType"> <assertThat testDocument="fonts/fonts_15_openoffice.pdf"> <hasFonts ofThisTypeOnly="TRUETYPE" /> </assertThat> </testcase>
Die prüfbaren Schrifttypen sind als Konstanten deklariert:
<!-- constants for font types -->
ofThisTypeOnly="CID"
ofThisTypeOnly="CID_TYPE0"
ofThisTypeOnly="CID_TYPE2"
ofThisTypeOnly="CJK"
ofThisTypeOnly="MMTYPE1"
ofThisTypeOnly="OPENTYPE"
ofThisTypeOnly="TRUETYPE"
ofThisTypeOnly="TYPE0"
ofThisTypeOnly="TYPE1"
ofThisTypeOnly="TYPE3"
Alle von PDFUnit intern verwendeten Schriftinformationen können mit dem
Extraktionsprogramm ExtractFontsInfo
nach XML exportiert
werden. Die erzeugte XML-Datei kann für Tests verwendet werden:
Die Datei enthält diese Informationen:
<?xml version="1.0" encoding="UTF-8" ?> <fontlist> ... <font name="Courier" baseFontName="Courier" type="Type1" embedded="false" encoding="WinAnsiEncoding" convertibleToUnicode="false" /> <font name="FGNNPL+ArialMT" baseFontName="ArialMT" type="TrueType" embedded="true" encoding="WinAnsiEncoding" convertibleToUnicode="false" /> ... </fontlist>
Ein Test gegen die XML-Datei sieht dann so aus:
<testcase name="hasFontsMatchingXML_ComparedAsFile"> <assertThat testDocument="fonts/fonts_52_itext.pdf"> <hasFonts> <matchingXML file="fonts/fonts_52_itext.xml" /> </hasFonts> </assertThat> </testcase>
Whitespaces spielen bei den Vergleichen mit der XML-Datei keine Rolle.
Auf der Basis der Schriftinformationen im XML-Format können anspruchsvolle Tests mit XPath-Abfragen umgesetzt werden:
<!-- This XML code needs double quotes outside and single quotes inside, because the generated Java code also needs double quotes outside. --> <testcase name="hasFontsMatchingXPath_MultipleInvocation"> <assertThat testDocument="fonts/fonts_52_itext.pdf"> <hasFonts> <matchingXPath expr="count(//font[@baseFontName='ArialMT']) = 1" /> <matchingXPath expr="count(//font[@type='Type1']) = 5" /> </hasFonts> </assertThat> </testcase>
Wenn Sie Problem mit XPath-Ausdrücken haben, exportieren Sie die Schriftinformationen
mit dem Extraktionsprogramm ExtractFontsInfo
und überprüfen den XPath-Ausdruck
direkt an der XML-Datei. Eclipse stellt dafür die „XPath“-View zur Verfügung.
Weitere Informationen zu XPath stehen im Kapitel 8: „XPath-Einsatz“.