3.19. Schriften

Überblick

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)
/>

Anzahl von Schriften

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>

Schriftnamen

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.

Schrifttypen

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"

XML-Datei als Referenz

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.

XPath-Abfrage auf Schriften

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“.