Frage

Mein Programm erzeugt relativ einfache PDF-Dokumente auf Anfrage, aber ich habe Probleme mit Unicode-Zeichen, wie Kanji oder ungerade mathematische Symbole. Um eine normale Zeichenfolge in PDF zu schreiben, Sie legen Sie sie in Klammern:

(something)

Es gibt auch die Möglichkeit, einen Charakter mit Oktalcodes zu entkommen:

(\527)

aber das geht nur auf 512 Zeichen. Wie codieren Sie oder höher Escape-Zeichen? Ich habe Verweise auf Byte-Streams und Hex-kodierten Strings gesehen, aber keine der Referenzen, die ich gelesen habe, scheint bereit zu sein, mir zu sagen, wie man es eigentlich zu tun.


Edit: Alternativ zeigen Sie mir eine gute Java PDF-Bibliothek, die den Job für mich tun wird. Der, den ich zur Zeit bin mit ist eine Version von gnujpdf (die ich einige Fehler behoben haben in, da der ursprüngliche Autor erscheint AWOL gegangen sein), dass Sie gegen eine AWT Graphics Interface zu programmieren, und im Idealfall sollte jeder Ersatz tun das gleiche.

Die Alternativen scheinen entweder HTML zu sein -> PDF oder ein programmatisches Modell, das auf den Absätzen und Boxen, die fühlen sich sehr ähnlich wie HTML. iText ist ein Beispiel für die letzteren. Das wäre meinen vorhandenen Code bedeutet, Umschreiben, und ich bin nicht überzeugt, dass sie mir die gleiche Flexibilität in Auslegen geben würden.


Edit 2: Ich habe nicht vor realisieren, aber die iText-Bibliothek hat eine Graphics2D API und scheint Unicode perfekt zu handhaben, so was das ist, ich verwenden werde. Obwohl es nicht eine Antwort auf die Frage, wie gefragt ist, löst es das Problem für mich.


Bearbeiten 3: iText arbeitet für mich schön. Ich denke, die Lektion ist, wenn sie mit etwas konfrontiert, die für jemanden pointlessly schwierig, schauen scheint, die mehr über sie, als man weiß.

War es hilfreich?

Lösung

Die einfache Antwort ist, dass es keine einfache Antwort. Wenn Sie einen Blick auf der PDF-Spezifikation übernehmen, werden Sie ein ganzes Kapitel sehen - und ein lang man an, dass - zu den Mechanismen der Textanzeige gewidmet. Ich implementiert alle die PDF-Unterstützung für meine Firma und die Handhabung Text war mit Abstand das komplexeste Teil der Übung. Die Lösung, die Sie entdeckt - eine 3rd-Party-Bibliothek verwenden, um die Arbeit für Sie zu tun -. Ist wirklich die beste Wahl, es sei denn, Sie haben sehr spezifische, Spezial-Anforderungen für Ihre PDF-Dateien

Andere Tipps

In der PDF-Referenz in Kapitel 3, das ist, was sie sagen über Unicode:

  

Textzeichenfolgen codiert werden in   entweder PDFDocEncoding oder Unicode-Zeichencodierung. PDFDocEncoding ist ein   Obermenge der ISO Latin 1-Kodierung und ist in Anhang D. Unicode dokumentiert   im Unicode-Standard vom Unicode Consortium beschrieben wird (siehe Literaturverzeichnis).   Für Text-Strings in Unicode codiert sind, müssen die ersten zwei Bytes werden 254, gefolgt von   255. Diese beiden Bytes stellen den Unicode Bytereihenfolge Marker, U + FEFF, was anzeigt,   dass die Zeichenfolge in der UTF-16BE (big-endian) Codierschemas codiert angegebenen   in dem Unicode-Standard. (Dieser Mechanismus schließt Beginn einer Zeichenfolge mit   PDFDocEncoding mit den beiden Dorn ydieresis Zeichen, die unwahrscheinlich ist,   sein ein sinnvoller Anfang eines Wortes oder Satzes).

Algoman Antwort ist falsch in vielen Dingen. Sie können ein PDF-Dokumente mit Unicode in es machen und es ist kein Hexenwerk, obwohl es einige Arbeit braucht. Ja, er ist richtig, mehr als 255 Zeichen in einer Schriftart verwenden Sie ein Composite-Schrift (CIDFont) pdf-Objekt erstellen. Dann erwähnen Sie nur die tatsächliche Truetype-Schriftart Sie als DescendatFont Eintrag von CIDFont verwenden möchten. Der Trick besteht darin, dass nach, dass Sie verwenden müssen Symbolindizes eine Schriftart anstelle von Zeichencodes. Um diese Indizes abbilden Sie cmap Abschnitt einer Schriftart zu analysieren haben - bekommen Inhalt der Schrift mit GetFontData Funktion und nehmen Sie die Hände auf TTF-Spezifikation. Und das ist es! Ich habe tat es einfach und jetzt habe ich eine Unicode pdf!

Beispielcode cmap Abschnitt zum Parsen ist hier: https://support.microsoft.com / en-us / kb / 241020

Und ja, nicht vergessen / ToUnicode Eintrag als @ user2373071 wies darauf hin, oder Benutzer Ihre PDF nicht oder Text suchen können kopieren von ihm.

Wie dredkin wies darauf hin, müssen Sie die Symbolindizes verwenden, anstatt den Unicode-Zeichenwert in dem Seiteninhalt Stream. Dies reicht aus, um Unicode-Text in PDF anzuzeigen, aber der Unicode-Text nicht durchsucht werden. Um den Text durchsuchbar oder haben Kopieren / Einfügen Arbeit auf sie zu machen, müssen Sie auch zählen ein / ToUnicode Stream. Dieser Strom soll jede Glyphe in dem Dokument zu den tatsächlichen Unicode-Zeichen übersetzen.

Siehe Anhang D (Seite 995) der PDF-Spezifikation. Es gibt eine begrenzte Anzahl von Schriftarten und Zeichensätze vordefiniert in einer PDF-Consumer-Anwendung. Um andere Zeichen anzuzeigen benötigen Sie eine Schrift einbetten, die sie enthält. Es ist auch bevorzugt, nur eine Teilmenge der Schrift einbetten, einschließlich nur erforderlichen Zeichen, um die Dateigröße zu reduzieren. Ich arbeite auch auf der Anzeige von Unicode-Zeichen in PDF und es ist ein großer Aufwand.

Überprüfen Sie heraus PDFBox oder iText.

http://www.adobe.com/devnet/pdf/pdf_reference.html

Ich habe zu diesem Thema mehrere Tage gearbeitet jetzt und was ich gelernt habe ist, dass Unicode (so gut wie) unmöglich in pdf ist. Unter Verwendung von 2-Byte-Zeichen der Art und Weise Sockel nur mit CID-Fonts arbeitet beschrieben.

scheinbar, CID-Fonts sind ein pdf-internes Konstrukt und sie sind nicht wirklich Schriften in diesem Sinne -. Sie scheinen eher wie Grafiken-Subroutinen zu sein, die von ihnen Rechnung geltend gemacht werden kann (mit 16-Bit-Adressen)

So verwenden Unicode in pdf direkt

  1. würden Sie normale Schriften zu CID-Fonts konvertieren müssen, die wahrscheinlich extrem hart ist - können Sie die Grafikroutinen aus der ursprünglichen Schriftart erzeugen müssen, extrahieren Zeichenmetriken usw.
  2. (?).
  3. Sie können nicht CID-Fonts wie normale Schriftarten verwenden - Sie können sie nicht die Art und Weise laden oder skalieren Sie normale Schriften
  4. laden und Skala
  5. auch, 2-Byte-Zeichen decken nicht einmal den vollen Unicode-Raum

IMHO, diese Punkte machen es absolut undurchführbar Unicode verwenden direkt .



Was ich stattdessen jetzt gerade die Zeichen wird mit indirekt in der folgenden Art und Weise: Für jede Schriftart, erstelle ich einen Zeichensatz (und eine Lookup-Tabelle für schnelle Lookups) - in C ++ dies so etwas wie

sein würde
std::map<std::string, std::vector<wchar_t> > Codepage;
std::map<std::string, std::map<wchar_t, int> > LookupTable;

dann, wenn ich eine Unicode-Zeichenkette auf einer Seite setzen wollen, ich iterieren seine Charaktere, schauen sie in der Lookup-Tabelle und - wenn sie neu sind, ich sie auf den Code-Seite wie folgt hinzu:

for(std::wstring::const_iterator i = str.begin(); i != str.end(); i++)
{                
    if(LookupTable[fontname].find(*i) == LookupTable[fontname].end())
    {
        LookupTable[fontname][*i] = Codepage[fontname].size();
        Codepage[fontname].push_back(*i);
    }
}

dann, ich erzeuge einen neuen String, in dem die Zeichen aus der ursprünglichen Zeichenkette durch ihre Positionen in der Codepage wie folgt ersetzt werden:

static std::string hex = "0123456789ABCDEF";
std::string result = "<";
for(std::wstring::const_iterator i = str.begin(); i != str.end(); i++)
{                
    int id = LookupTable[fontname][*i] + 1;
    result += hex[(id & 0x00F0) >> 4];
    result += hex[(id & 0x000F)];
}
result += ">";

zum Beispiel "H € llo World!" werden könnten <01020303040506040703080905> und jetzt können Sie nur die Zeichenfolge in das pdf setzen und haben es gedruckt, die Tj Operator wie gewohnt mit ...

, aber Sie haben jetzt ein Problem: die pdf wissen nicht, dass Sie von einem 01. „H“ bedeutet, dieses Problem zu lösen, müssen Sie auch die Codepage in der pdf-Datei enthalten. Dies geschieht durch Hinzufügen eines / Encoding auf das Font-Objekt gesetzt und seine Unterschiede

Für das "H € llo World!" Beispiel dieses Font-Objekt funktionieren würde:

5 0 obj 
<<
    /F1
    <<
        /Type /Font
        /Subtype /Type1
        /BaseFont /Times-Roman
        /Encoding
        <<
          /Type /Encoding
          /Differences [ 1 /H /Euro /l /o /space /W /r /d /exclam ]
        >>
    >> 
>>
endobj 

ich generiere es mit diesem Code:

ObjectOffsets.push_back(stream->tellp()); // xrefs entry
(*stream) << ObjectCounter++ << " 0 obj \n<<\n";
int fontid = 1;
for(std::list<std::string>::iterator i = Fonts.begin(); i != Fonts.end(); i++)
{
    (*stream) << "  /F" << fontid++ << " << /Type /Font /Subtype /Type1 /BaseFont /" << *i;

    (*stream) << " /Encoding << /Type /Encoding /Differences [ 1 \n";
    for(std::vector<wchar_t>::iterator j = Codepage[*i].begin(); j != Codepage[*i].end(); j++)
        (*stream) << "    /" << GlyphName(*j) << "\n";
    (*stream) << "  ] >>";

    (*stream) << " >> \n";
}
(*stream) << ">>\n";
(*stream) << "endobj \n\n";

Beachten Sie, dass ich ein globales font-Register verwenden - ich verwende den gleichen Font-Namen / F1, / F2, ... während des gesamten PDF-Dokument. Das gleiche font-Register Objekt wird in der / Ressourcen Eingabe aller Seiten verwiesen wird. Wenn Sie dies anders machen (zum Beispiel verwenden Sie eine font-Register pro Seite) - Sie könnten den Code auf Ihre Situation anpassen müssen ...

Wie finden Sie die Namen der Glyphen (/ Euro für "€", / exclam für "!" Etc.)? In dem obigen Code wird dies durch einfach gemacht „glyphname (* j)“ aufrufen. Ich habe diese Methode mit einem BASH-Script aus der bei

gefunden Liste erzeugt

http://www.jdawiseman.com/papers/trivia/character- entities.html

und es sieht wie folgt aus

const std::string GlyphName(wchar_t UnicodeCodepoint)
{
    switch(UnicodeCodepoint)
    {
        case 0x00A0: return "nonbreakingspace";
        case 0x00A1: return "exclamdown";
        case 0x00A2: return "cent";
        ...
    }
}

großes Problem Ich habe offen gelassen ist, dass dieses funktioniert nur so lange, wie Sie bei den meisten verwenden 254 verschiedene Zeichen aus der gleichen Schriftart. Um mehr als 254 verschiedene Zeichen zu verwenden, würden Sie mehrere Codepages für die gleiche Schriftart erstellen müssen.

Im Innern der pdf, verschiedener Codepages durch verschiedene Schriftarten dargestellt werden, so zwischen Codepages zu wechseln, würden Sie Schriftarten wechseln müssen, die theoretisch Ihre pdf nach oben ziemlich viel blasen können, aber ich für meinen Teil, kann damit leben .. .

Ich bin kein PDF-Experte, und die PDF-Spezifikationen bei Adobe (wie Ferruccio sagte) sollten Sie alles erzählen, aber ein Gedanke tauchte in meinem Kopf:

Sind Sie sicher, dass Sie eine Schriftart verwenden, die alle Zeichen unterstützt Sie brauchen?

In unserer Anwendung, wir erstellen PDF aus HTML-Seiten (mit einem Dritten Bibliothek), und wir hatten dieses Problem mit kyrillischen Zeichen ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top