THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA-Allokator für synthetische Codepoints (v2.119.68)

 

GSUB-Engine  Automatische Formungspipeline  Arabische Formung

Allokiert und fragt synthetische Codepoints im Private Use Area (U+E000 - U+F8FF) für OpenType GSUB-Ersatz-GIDs ab, die keinen natürlichen Unicode-Codepoint besitzen, der über die cmap der Schriftart erreichbar ist; schließt die erzeugerseitige Emissionslücke auf GID-Ebene, die durch die GSUB-Abfrage- und Verfeinerungs-APIs in v2.119.43-66 hinterlassen wurde

 

Delphi-Syntax:

function AssignSyntheticCodepointForGID(GID: Word; out SyntheticCP: Word): Boolean;

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Warum die API existiert

Die erzeugerseitige automatische Formungspipeline in v2.119.32-67 (Arabisch / Lateinisch / Devanagari) erfordert, dass vom GSUB-Engine zurückgegebene Ersatz-GIDs über einen Unicode-Codepoint erreichbar sind — die bestehende hexadezimal codierte Textpipeline gibt Codepoints und keine GIDs aus, und der Reader auf Clientseite löst den Codepoint über die eingebettete /CIDToGIDMap wieder in eine GID auflöst; für Ersatz-GIDs, die einen natürlichen Unicode-Codepoint über die cmap der Schriftart besitzen (Arabische Präsentationsformen, lateinische Standardligaturen FB00-FB06), funktioniert die bestehende Pipeline einwandfrei

 

Schriftartspezifische Ersatzzeichen, die auf schriftartinternen GIDs landen — die meisten Devanagari-Clusterformen, stilistische Alternativen, die der Schriftdesigner nur als nummerierte GIDs bereitstellt, CJK-ideografische Variationssequenzen (IVS), diskretionäre Ligaturen ohne entsprechende Präsentationsform —, haben jedoch überhaupt keinen Codepoint in der cmap der Schriftart; vor Version v2.119.68 waren diese GIDs über die erzeugerseitige Hex-Pipeline unerreichbar; v2.119.68 schließt diese Lücke, indem Aufrufer einen synthetischen Codepoint im Private Use Area für jede beliebige GID allokieren können

 

Semantik von AssignSyntheticCodepointForGID

Allokiert den nächsten verfügbaren PUA-Codepoint (beginnend bei U+E000) für die angegebene GID und spiegelt die Zuweisung in jedem Cache wider, von dem die bestehende erzeugerseitige Hex-Pipeline und die Auflösungskette des Client-Readers abhängen:

 

1. FUnicodeCpToGid[SyntheticCP] := GID — damit die erzeugerseitige Hex-Pipeline SyntheticCP in den Textanzeige-Operator schreibt und der Client-Reader SyntheticCP beim Rendern über die /CIDToGIDMap wieder in die GID auflöst

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction — damit der Zeilenumbruch-Rechner in v2.65 die korrekte hmtx-Breite für den synthetischen Codepoint findet, wenn dieser im Inhalt von AcroForm-Textfeldern erscheint

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP — die GID-basierte Reverse-Lookup-Tabelle, die von GetSyntheticCodepointForGID verwendet wird, um wiederholte Aufrufe von AssignSyntheticCodepointForGID idempotent zu machen (der zweite Aufruf mit derselben GID gibt den bereits allokierten synthetischen Codepoint zurück)

 

Gibt bei Erfolg True zurück, wobei SyntheticCP auf den allokierten Codepoint gesetzt wird; gibt unter einer dieser defensiven Bedingungen False zurück (und belässt SyntheticCP bei 0): keine Schriftart registriert (RegisterUnicodeTTF wurde nie aufgerufen oder mit leeren Argumenten aufgerufen, um den Zustand zurückzusetzen), ungültige GID (Null oder außerhalb der Glyphenanzahl der cmap), PUA-Bereich erschöpft (alle 6400 Slots U+E000 - U+F8FF allokiert), Cache beim Eintritt nicht initialisiert

 

Semantik von GetSyntheticCodepointForGID

Rein funktionale Abfrage jeder bestehenden Zuweisung; gibt den für die GID allokierten synthetischen Codepoint zurück, falls AssignSyntheticCodepointForGID(GID, ...) zuvor aufgerufen wurde; andernfalls wird 0 zurückgegeben (was kein gültiger PUA-Codepoint ist und somit als Signal für „keine Zuweisung“ dient); allokiert nicht; kann sicher aufgerufen werden, bevor ein Aufruf von AssignSyntheticCodepointForGID erfolgt ist

 

Lebenszyklus des Allokatorzustands

FUnicodeSyntheticCpForGID und der Zeiger auf den nächsten verfügbaren PUA-Codepoint (FUnicodeNextSyntheticCp) werden beim ersten Aufruf von AssignSyntheticCodepointForGID verzögert allokiert; der Zeiger beginnt bei 0 (nicht initialisiert) und springt bei der ersten Allokation auf $E000; nachfolgende Allokationen bewegen ihn durch $E001, $E002, ..., $F8FF; beide Felder werden bei jedem RegisterUnicodeTTF('', nil) zusammen mit dem restlichen Subset-Zustand pro Schriftart auf leer / 0 zurückgesetzt, sodass Aufrufer, die eine THotPDF-Instanz über mehrere Dokumente hinweg wiederverwenden, jedes Dokument mit einem frischen PUA-Zeiger beginnen

 

Typischer Arbeitsablauf (Devanagari-Clusterform)

 

PDF.RegisterUnicodeTTF('NotoDeva', 'NotoSansDevanagari-Regular.ttf');

PDF.ShapingFeatures := [sfIndicShaping];

PDF.SetGSUBScript('deva');

 

// Ermitteln einer schriftartinternen Cluster-GID über die GSUB-Engine

ClusterGID := PDF.GetSingleSubstituteGlyph(BaseGID, 'nukt');

if ClusterGID <> BaseGID then

begin

  // Prüfen, ob die cmap den Ersatz erreicht — bei Indisch-Clustern

  // in der Regel nein, da Cluster-GIDs schriftartintern sind

  // Allokieren eines synthetischen Codepoints, den die erzeugerseitige

  // Hex-Pipeline ausgeben kann

  if PDF.AssignSyntheticCodepointForGID(ClusterGID, SyntheticCP) then

  begin

    // SyntheticCP liegt nun im Bereich U+E000-F8FF range; Ausgabe

    // über UnicodeTextOut wie ein normaler Codepoint

    PDF.CurrentPage.UnicodeTextOut(X, Y, 0, UnicodeChar(SyntheticCP));

    PDF.MarkUnicodeGlyphUsed(ClusterGID);

  end;

end;

 

Beispiel für Idempotenz

 

PDF.AssignSyntheticCodepointForGID(150, CP1);  // CP1 = $E000

PDF.AssignSyntheticCodepointForGID(151, CP2);  // CP2 = $E001

PDF.AssignSyntheticCodepointForGID(150, CP3);  // CP3 = $E000 (idempotent)

CP4 := PDF.GetSyntheticCodepointForGID(150);  // CP4 = $E000

CP5 := PDF.GetSyntheticCodepointForGID(999);  // CP5 = 0 (keine Zuweisung)

 

Verhalten des Client-Readers

Der Client-Reader sieht den PUA-Codepoint im Textanzeige-Operator, löst ihn über die im Dokument eingebettete /CIDToGIDMap in die Ziel-GID auf und rendert diese GID anschließend mithilfe des eingebetteten Schriftartprogramms; aus Sicht des Readers gibt es keinen Unterschied zwischen einem „natürlichen“ Unicode-Codepoint, den die cmap zur GID leitet, und einem synthetischen PUA-Codepoint, den die /CIDToGIDMap zur GID leitet — beide erzeugen dieselbe gerenderte Glyphe

 

Kopier- und Einfügeverhalten: PUA-Codepoints werden beim Kopieren und Einfügen als sie selbst übertragen, wenn die ToUnicode-CMap sie als Identitätszuordnungen deklariert; Aufrufer, die stattdessen die ursprünglichen Unicode-Zeichen (die Eingabesequenz, die den Ersatz erzeugt hat) übertragen möchten, können eine umgekehrte Zuordnung mit RegisterToUnicodeReverseMapping registrieren oder ActualText-Eigenschaften für markierte Inhaltssequenzen über BeginTaggedContent erstellen und die synthetischen Codepoints innerhalb des eingeklammerten Inhalts ausgeben; HotPDF verwendet dasselbe interne CID-Muster automatisch für RegisterUnicodeTTF-gestützte AcroForm-Darstellungsströme, die Unicode-Zeichen aus ergänzenden Ebenen enthalten

 

Abschluss der Phase 8 Roadmap

v2.119.68 / Phase 8c.6 schließt die Phase 8 GSUB-Engine-Roadmap ab: Jede LookupType 1-8 Abfrage-API (Phase 1-6), die Script- / LangSys-Auswahl-API (Phase 7), der Einstiegspunkt für das TTF-Subsetting-Closure (Phase 9), das statische Ligatur-Folding im Post-Pass (v2.119.32 / 58 / 60 / 62), die optionale automatische Pipeline (v2.119.59), die automatische Ausgabe von arabischem rlig und lateinischem liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), das ToUnicode-Reverse-Mapping (v2.119.61 / 62 / 65), die Breitenabfrage (v2.119.64), der Devanagari-Indic-Reorder-Pre-Pass (v2.119.67) und nun die PUA-Synthetik-Codepoint-Emission auf GID-Ebene (v2.119.68) integrieren sich alle in eine einzige erzeugerseitige Formungsoberfläche, die jede Art von Ersatzglyphe verarbeitet, die eine OpenType-Schriftart erzeugen kann

 

Siehe auch: OpenType GSUB-Ersetzungs-Engine, Automatische Formungspipeline (Phase 8), Unterstützung für Arabisch / Persisch / Urdu, Syrisch / Mongolisch / Devanagari-Formung, THotPDF.BeginTaggedContent