THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Alloue et interroge des points de code synthétiques de la Private Use Area (U+E000 - U+F8FF) pour les GID de substitution OpenType GSUB qui n’ont pas de point de code Unicode naturel atteignable via la table cmap de la police Comble le manque d’émission au niveau GID côté producteur laissé par les API de requête et de raffinage GSUB v2.119.43-66

 

Syntaxe Delphi :

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Pourquoi cette API existe

Le pipeline automatique de façonnage côté producteur v2.119.32-67 (Arabic / Latin / Devanagari) exige que les GID de substitution renvoyés par le moteur GSUB soient atteignables via un point de code Unicode - le pipeline de texte encodé en hexadécimal existant émet des points de code, pas des GID, et le lecteur consommateur résout le point de code vers un GID via le /CIDToGIDMap embarqué Pour les GID de substitution qui possèdent un point de code Unicode naturel via la table cmap de la police (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), le pipeline existant fonctionne correctement

 

Mais les substitutions spécifiques à une police qui retombent sur des GID internes à la police - la plupart des formes de cluster Devanagari, les alternances stylistiques livrées par le concepteur de police uniquement sous forme de GID numérotés, les séquences de variation idéographique CJK (IVS), les ligatures discrétionnaires sans forme de présentation correspondante - n’ont aucun point de code dans la table cmap de la police Avant v2.119.68, ces GID étaient inaccessibles via le pipeline hexadécimal côté producteur ; v2.119.68 comble ce manque en permettant d’allouer à n’importe quel GID un point de code synthétique dans la Private Use Area

 

Sémantique de AssignSyntheticCodepointForGID

Alloue le prochain point de code PUA disponible (en commençant à U+E000) pour le GID fourni et répercute l’affectation dans tous les caches dont dépend la chaîne existante de pipeline hexadécimal côté producteur + résolution côté lecteur :

 

1. FUnicodeCpToGid[SyntheticCP] := GID - afin que le pipeline hexadécimal côté producteur émette SyntheticCP dans l’opérateur d’affichage du texte et que le lecteur consommateur résolve SyntheticCP vers GID via /CIDToGIDMap au moment du rendu

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - afin que le calculateur de retour à la ligne v2.65 trouve l’avance hmtx correcte pour le point de code synthétique lorsqu’il apparaît dans le contenu des champs de texte AcroForm

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - la table de recherche inverse par GID utilisée par GetSyntheticCodepointForGID pour rendre les appels répétés à AssignSyntheticCodepointForGID idempotents (le second appel avec le même GID renvoie le SyntheticCP déjà alloué)

 

Renvoie True en cas de réussite, avec SyntheticCP positionné sur le point de code alloué Renvoie False (et laisse SyntheticCP à 0) dans l’un des cas défensifs suivants : aucune police enregistrée (RegisterUnicodeTTF jamais appelée ou appelée avec des arguments vides pour réinitialiser l’état), GID invalide (zéro ou au-delà du nombre de glyphes de la cmap), plage PUA épuisée (les 6400 emplacements U+E000 - U+F8FF sont alloués), cache non initialisé à l’entrée

 

GetSyntheticCodepointForGID semantics

Requête purement fonctionnelle sur une affectation existante Renvoie le point de code synthétique alloué pour GID si AssignSyntheticCodepointForGID(GID, ...) a déjà été appelée ; sinon renvoie 0 (qui n’est pas un point de code PUA valide et sert donc de sentinelle "aucune affectation") N’alloue rien Peut être appelée sans risque avant toute exécution de AssignSyntheticCodepointForGID

 

Cycle de vie de l’allocateur

FUnicodeSyntheticCpForGID et le curseur PUA suivant disponible (FUnicodeSuivantSyntheticCp) sont alloués à la demande au premier appel à AssignSyntheticCodepointForGID Le curseur commence à 0 (non initialisé) puis passe à $E000 lors de la première allocation ; les allocations suivantes le font avancer vers $E001, $E002, ..., $F8FF Les deux champs sont remis à vide / 0 à chaque RegisterUnicodeTTF('', nil), avec le reste de l’état de sous-ensemble propre à la police, de sorte que les appelants qui réutilisent une instance THotPDF sur plusieurs documents recommencent chaque document avec un curseur PUA neuf

 

Workflow type (Devanagari cluster shape)

 

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

PDF.ShapingFeatures := [sfIndicShaping];

PDF.SetGSUBScript('deva');

 

// Get a font-internal cluster GID through the GSUB engine

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

if ClusterGID <> BaseGID then

begin

  // Check if cmap reaches the substitute - usually no for Indic

  // clusters, since cluster GIDs are font-internal

  // Allocate a synthetic codepoint that the producer-side

  // hex pipeline can emit

  if PDF.AssignSyntheticCodepointForGID(ClusterGID, SyntheticCP) then

  begin

    // SyntheticCP is now in the U+E000-F8FF range; emit it

    // through UnicodeTextOut just like a normal codepoint

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

    PDF.MarkUnicodeGlyphUsed(ClusterGID);

  end;

end;

 

Idempotency example

 

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 (no assignment)

 

Comportement du lecteur consommateur

Le lecteur consommateur voit le point de code PUA dans l’opérateur d’affichage du texte et le résout via le /CIDToGIDMap incorporé au document vers le GID cible, puis rend ce GID à l’aide du programme de police embarqué Du point de vue du lecteur, il n’y a aucune différence entre un point de code Unicode "naturel" que la cmap dirige vers GID et un point de code synthétique PUA que /CIDToGIDMap dirige vers GID - les deux produisent le même glyphe rendu

 

Comportement copier / coller : les points de code PUA effectuent un aller-retour tels quels lors du copier / coller lorsque la CMap ToUnicode les déclare comme mappages d’identité Les appelants qui veulent que les caractères Unicode source (la séquence d’entrée qui a produit la substitution) effectuent l’aller-retour à la place peuvent enregistrer un mappage inverse avec RegisterToUnicodeReverseMapping ou rédiger des propriétés de séquence de contenu marqué ActualText via BeginTaggedContent et émettre les points de code synthétiques à l’intérieur du contenu entre crochets HotPDF utilise automatiquement le même schéma interne CID pour les flux d’apparence AcroForm basés sur RegisterUnicodeTTF qui contiennent des caractères Unicode du plan supplémentaire

 

Clôture de la feuille de route de la phase 8

v2.119.68 / Phase 8c.6 clôt la feuille de route du moteur GSUB Phase 8 : toutes les API de requête LookupType 1-8 (Phases 1-6), l’API de sélection Script / LangSys (Phase 7), le point d’entrée de clôture du sous-ensemble TTF (Phase 9), le pliage de ligatures en post-traitement statique (v2.119.32 / 58 / 60 / 62), le pipeline automatique à activation explicite (v2.119.59), l’émission automatique rlig arabe + liga / clig + rclt latin (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), le remappage inverse ToUnicode (v2.119.61 / 62 / 65), la requête d’avance (v2.119.64), le pré-pass de réordonnancement Indic Devanagari (v2.119.67) et désormais l’émission de points de code synthétiques PUA au niveau GID (v2.119.68) s’intègrent tous dans une surface de façonnage côté producteur unique qui gère tout type de glyphe de substitution qu’une police OpenType peut produire

 

Voir aussi: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Prise en charge du façonnage arabe / persan / ourdou, Syriac / Mongolian / Devanagari Shaping, THotPDF.BeginTaggedContent