Technischer Artikel

Complex Script Text Shaping in Delphi mit HotPDF

Das Drucken von lateinischem Text in ein PDF ist unkompliziert: Sie weisen einem Zeichencode eine Glyphe zu, rücken um die Breite der Glyphe vor und wiederholen den Vorgang. Wenn Sie diese Logik auf Arabisch, Thai oder Hindi anwenden, erhalten Sie unleserlichen Text. Arabische Buchstaben ändern ihre Form je nach angrenzenden Zeichen; Hindi-Konsonanten verschmelzen zu neuen Ligaturen (Conjuncts); thailändische Vokale stapeln sich über und unter Basiszeichen. HotPDF verarbeitet diese Sprachen über eine Shaping-Engine, die rohe Unicode-Strings in korrekt positionierte Glyphen-Cluster für die PDF-Ausgabe übersetzt

Das HarfBuzz-DLL-Requirement

HotPDF verlässt sich für sein Complex Text Shaping auf HarfBuzz, die gleiche Open-Source-Engine, die von Chrome und Firefox verwendet wird. Es erfordert, dass die libharfbuzz-0.dll (oder die 64-Bit-Entsprechung) zur Laufzeit verfügbar ist. Wenn Sie versuchen, komplexen Text zu zeichnen, während die DLL fehlt, greift HotPDF auf seine integrierte lateinische Engine zurück, was bedeutet, dass arabische Buchstaben unverbunden (isoliert) gezeichnet und von links nach rechts geschrieben werden

Die DLL muss sich entweder neben Ihrer ausführbaren Datei, in einem Verzeichnis, auf das über den Systempfad zugegriffen werden kann, oder in dem durch THotPDF.HarfBuzzLibraryPath angegebenen Pfad befinden. Dies ist ein Laufzeit-Requirement, das mit Ihrer Anwendung bereitgestellt werden muss

Aktivieren des Shaping

Das Shaping ist standardmäßig deaktiviert, um die Abwärtskompatibilität und Leistung bei Legacy-Berichten aufrechtzuerhalten. Sie aktivieren es für das gesamte Dokument, indem Sie UseTextShaping := True setzen, bevor Sie den ersten Textaufruf tätigen

Pdf := THotPDF.Create(nil);
Pdf.UseTextShaping := True;
Pdf.TextDirection := tdRightToLeft;
Pdf.CurrentPage := Pdf.AddPage;

Sie müssen auch festlegen, wie Text gerichtet (ausgerichtet) ist. Für Sprachen, die von rechts nach links (RTL) gelesen werden, wie Arabisch oder Hebräisch, setzen Sie TextDirection := tdRightToLeft. Bei Thai oder Hindi behalten Sie den Standardwert (tdLeftToRight) bei. Die Richtungsänderung weist HarfBuzz nicht nur an, die Glyphenfolge umzukehren; sie wirkt sich grundlegend auf Formungsregeln wie arabische Anfangs-/Mittel-/Endformen und Klammer-Spiegelung (Bracket Mirroring) aus

TTF-Schriftarten sind obligatorisch

Standard-PDF-Schriftarten (Helvetica, Times, Courier) enthalten nicht die Tabellen für komplexe Skripte oder die Tausenden von Glyphen, die erforderlich sind. Das Shaping erfordert eine physische TrueType- oder OpenType-Schriftart, die Sie in das Dokument laden und einbetten

// Load a font that supports the target script
Pdf.AddFontFilePath('C:\Windows\Fonts\tahoma.ttf', 'Tahoma');
Pdf.SetFont('Tahoma', 14);

// Draw the text (coordinates are handled differently in RTL mode)
Pdf.TextOut(Pdf.PageWidth - 50, 100, 'مرحبا بالعالم');

Es reicht nicht aus, einfach eine beliebige TrueType-Schriftart zu haben; die Schriftart muss die spezifische Sprache unterstützen, die Sie formen möchten. Wenn Sie versuchen, Arabisch mit Arial zu zeichnen, wird die Engine quadratische Kästchen (die .notdef-Glyphe) ausgeben, weil Arial nicht die OpenType-Arabic-Tabellen enthält, die HarfBuzz für das Shaping benötigt. Verwenden Sie Schriftarten wie Tahoma, Arial Unicode MS oder plattformspezifische UI-Schriftarten wie Segoe UI

Bidirektionaler (BiDi) Text

Ein häufiges Szenario in Rechnungs- oder Berichterstellungssystemen ist Text, der sowohl Englisch als auch Arabisch in derselben Zeichenfolge mischt, wie z. B. "Invoice Number 12345 (رقم الفاتورة)"

HotPDF führt derzeit keine vollständige Aufteilung in BiDi-Läufe durch. Wenn Sie TextDirection := tdRightToLeft setzen, wird die gesamte Zeichenfolge von rechts nach links verarbeitet. Wenn Sie sie auf tdLeftToRight setzen, wird die Zeichenfolge von links nach rechts verarbeitet. Eine Zeichenfolge mit gemischter Richtung auf niedriger Ebene verlangt, dass die Aufrufer-Anwendung sie in homogene Läufe (rein LTR und rein RTL) aufteilt und diese Läufe einzeln unter Beibehaltung der x-Koordinaten-Vorwärtsbewegung zeichnet. Für einfache Fälle bewältigt der RTL-Modus eingebettete Zahlen recht gut, kann aber bei eingebetteten englischen Wörtern zu Problemen mit der Wortreihenfolge führen

Thai und Vokalstapelung

Die thailändische Schrift ist keine RTL-Schrift, gehört aber aufgrund von Tone Marks und Vokalen, die über oder unter Konsonanten gestapelt werden, zur Kategorie Complex Script. Ohne Shaping zeichnet ein PDF-Renderer diese Markierungen nebeneinander, wodurch der Text unleserlich wird

Stellen Sie bei Thai sicher, dass Sie UseTextShaping := True setzen, aber belassen Sie TextDirection bei tdLeftToRight. Thailändische Schriftarten weisen stark unterschiedliche Basislinien auf; prüfen Sie Pdf.TextHeight sorgfältig, um vertikale Überlappungen in mehrzeiligen Absätzen zu vermeiden

Leistungsauswirkungen

HarfBuzz-Shaping ist schnell, erfordert jedoch eine erhebliche Speicherauslastung, wenn die libharfbuzz die TTF-Tabellen in den Speicher lädt. Dies geschieht in dem Moment, in dem der erste Text für eine bestimmte Schriftart geformt (shaped) wird. Wenn Sie Tausende von Rechnungen in einer Schleife generieren, erstellen Sie nicht pro Rechnung ein neues THotPDF-Objekt und laden die Schriftart nicht jedes Mal neu. Erstellen Sie eine THotPDF-Instanz, laden Sie die Schriftart einmalig, iterieren Sie, um Dokumente zu generieren und zu speichern, und geben Sie die Instanz am Ende frei