====== Direktzugriff ====== Diese Methode funktioniert mit allen TrueType/OpenType Schriften, ist aber natürlich mit mehr Aufwand verbunden. Aus der Schrift müssen wir für alle Unicode-Nummern die GID und Schriftbreite ermitteln. Zudem müssen wir eine umgekehrte Tabelle von den GIDs auf die Unicode-Nummern erstellen (zumindest, wenn wir den ToUnicode-Stream befüllen wollen). Die GID 0 kann man dabei ignorieren. Ist eine GID mehreren Unicode-Nummern zugeordnet, so sollte man die Kleinste nehmen. ===== das Teilschriftobjekt ===== Im Eintrag ''/W'' müssen die Zeichenbreiten nach GID sortiert angegeben werden. Es gibt keinen Eintrag ''/CIDToGIDMap''. ===== der Schriftstream ===== Bei OpenType Type1 und OpenType CID wird ''/Subtype'' auf ''/CIDType0C'' gesezt. ===== der ToUnicode Stream ===== ==== Grundlagen ==== Mit dem ToUnicode Stream teilen wir dem PDF Interpreter mit, wie er von den GIDs in den Strings auf Unicode-Nummern kommen soll. Hierfür werden mehrere Segmente von GIDs definiert, und die Unicodes der GIDs in diesem Segment angegeben. Für die Segmente gelten folgende Regeln: - GIDs, zu denen wir den Unicode nicht wissen, sollten in keinem Segment sein. - GIDs und Unicodenummern werden in Big-Endian Anordnung notiert. - Das jeweils erste Byte der ersten und der letzten GID eines Segments muss identisch sein. Punkt 3 der Liste bedeutet, dass wir zum Beispiel ein Segment 0x1000 - 0x10A0 definieren können, aber nicht ein Segment 0x10A0 - 0x1110. Dies zu ignorieren ist einer der häufigsten Fehler. Es gibt zwei Arten von Segmenten: Mit analogen oder nicht-analogen Unicode-Nummern. "Analog" bedeutet in diesem Fall, dass die Unicode-Nummern gleich wie die GIDs ansteigen. Ein Beispiel wäre ein GID Segment 0x1000 - 0x10A0 mit Unicode-Nummern 0x2030 - 0x20D0. Leider muss hier auch das erste Byte der ersten und der letzten Unicode-Nummer identisch sein. Ein Segment mit Unicode-Nummern 0x20A0 - 0x2140 können wir also nicht definieren, sondern wir müssen dies auf zwei Segmente aufteilen. Jeweils bis zu 100 Segmente werden zu einem Segmentblock zusammengefasst. Es können beliebig viele Segmentblocks verwendet werden. Neben den Segmenten können auch Zuweisungen für einzelne GIDs definiert werden. Das macht Sinn, wenn ein Segment ansonsten aus einem einzelnen Eintrag bestehen würde. Jeweils bis zu 100 Einzelzuweisungen werden zu einem Block zusammengefasst. Es können beliebig viele Einzelzuweisungsblocks verwendet werden. ==== Streaminhalt ==== Der ToUnicode-Stream beginnt immer mit folgenden Zeilen: /CIDInit /ProcSet findresource begin 12 dict begin begincmap Daraufhin folgt eine Zeile, welche die GID-Anordnung der Schrift eindeutig benennt. Es gibt verschiedene Arten, dies zu formulieren, aber eine gängige Methode geht so: ''/CIDSystemInfo %%<<%% /Registry (FontSpecific) /Ordering (//Schriftname//) /Supplement 0 %%>>%% def'' Wobei //Schriftname// identisch zu ''/BaseFont'' gesetzt werden sollte (aber als String, nicht als Namenobjekt). Direkt danach folgt eine Zeile, welche der ToUnicode Definition einen eindeutigen Namen gibt. Diese kann man zum Beispiel so setzen: ''/CMapName /FontSpecific-//Schriftname// def'' Wenn wir also zum Beispiel eine Schrift "MyFont" haben, so sieht dies so aus: /CIDSystemInfo << /Registry (FontSpecific) /Ordering (MyFont) /Supplement 0 >> def /CMapName /FontSpecific-MyFont def Nun folgen immer folgende Zeilen: /CMapType 2 def 1 begincodespacerange <0000> endcodespacerange Danach kommen nacheinander die Einzelzuweisungsblocks und Segmentblocks. Die Reihenfolge ist egal. Jeder Einzelzuweisungsblock beginnt mit folgender Zeile: ''//x// beginbfchar'' Wobei //x// die Anzahl Zuweisungen innerhalb des Blocks ist. Der Block endet mit der Zeile: ''endbfchar'' Innerhalb des Zuweisungsblocks schreibt man für jede Zuweisung eine Zeile. Auf diese Zeile kommen zwei durch einen Leerschlag getrennte Einträge. Der erste Eintrag ist die GID als Hexstring, der zweite Eintrag die Unicode-Nummer als Hexstring. Da sowohl GIDs wie auch Unicode-Nummern in einer 2-Byte Kodierung sind, braucht es immer 4 Hexziffern. Beispiel: 1 beginbfchar <0003> <0020> endbfchar Die GID 3 zeigt also auf die Unicode-Nummer 0x20. Segmentblocks sind ähnlich aufgebaut. Sie beginnen mit folgender Zeile: ''//x// beginbfrange'' Wobei //x// die Anzahl Segmente innerhalb des Blocks ist. Der Block endet mit einer Zeile: ''endbfrange'' Innerhalb des Segmentblocks schreibt man für jedes Segment eine Zeile. Auf diese Zeile kommen drei durch Leerschläge getrennte Einträge. Der erste Eintrag ist die erste GID des Segments als Hexstring. Der zweite Eintrag ist die letzte GID des Segments als Hexstring. Der dritte Eintrag ist entweder ein Array mit Unicode-Nummern (falls nicht-analog) oder die Unicode-Nummer der ersten GID (falls analog). Auch hier gilt: Da GID und Unicode-Nummern mit 2 Bytes kodiert sind, braucht es immer 4 Hexziffern. Beispiel: 2 beginbfrange <0010> <00A0> <2030> <10B0> <10B3> [<2040> <2050> <2060> <2070>] endbfrange Das heisst, dass im GID-Segment 0x0010 - 0x00A0 die Unicode-Nummern von 0x2030 nach 0x20C0 aufsteigen, während im GID-Segment 0x10B0 - 0x10B3 die Unicode-Nummern nacheinander 0x2040, 0x2050, 0x2060 und 0x2070 sind. Nachdem alle Blöcke definiert sind, kommen noch fix folgende Zeilen: endcmap CMapName currentdict /CMap defineresource pop end end Das gesamte Beispiel: /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo << /Registry (FontSpecific) /Ordering (MyFont) /Supplement 0 >> def /CMapName /FontSpecific-MyFont def /CMapType 2 def 1 begincodespacerange <0000> endcodespacerange 1 beginbfchar <0003> <0020> endbfchar 2 beginbfrange <0010> <00A0> <2030> <10B0> <10B3> [<2040> <2050> <2060> <2070>] endbfrange endcmap CMapName currentdict /CMap defineresource pop end end