THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF alocator de codepointuri sintetice PUA (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Alocă și interoghează codepointuri sintetice din Private Use Area (U+E000 - U+F8FF) pentru GID-urile de substituție OpenType GSUB care nu au un codepoint Unicode natural accesibil prin cmap-ul fontului. Închide golul de emitere la nivel de GID de pe partea producătorului, rămas de la API-urile de interogare și rafinare GSUB v2.119.43-66

 

Sintaxă Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

De ce există API-ul

Pipeline-ul automat de formare de pe partea producătorului din v2.119.32-67 (arabic / latin / devanagari) cere ca GID-urile de substituție returnate de motorul GSUB să poată fi atinse printr-un codepoint Unicode - pipeline-ul existent de text codificat hex emite codepointuri, nu GID-uri, iar cititorul consumator rezolvă codepointul înapoi la un GID prin /CIDToGIDMap încorporat. Pentru GID-urile de substituție care au un codepoint Unicode natural prin cmap-ul fontului (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), pipeline-ul existent funcționează corect

 

Dar substituțiile specifice fontului care ajung la GID-uri interne ale fontului - majoritatea formelor de cluster Devanagari, alternativele stilistice pe care designerul le livrează doar ca GID-uri numerotate, secvențele de variație ideografică CJK (IVS), ligaturile discreționare fără Presentation Form corespunzător - nu au niciun codepoint în cmap-ul fontului. Înainte de v2.119.68, aceste GID-uri nu puteau fi atinse prin pipeline-ul hex de pe partea producătorului; v2.119.68 închide acest gol permițând apelanților să aloce un codepoint sintetic în Private Use Area pentru orice GID

 

Semantica AssignSyntheticCodepointForGID

Alocă următorul codepoint PUA disponibil (începând cu U+E000) pentru GID-ul furnizat și oglindește atribuirea în fiecare cache de care depinde lanțul existent de rezolvare al pipeline-ului hex de pe partea producătorului + al cititorului consumator:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - astfel încât pipeline-ul hex de pe partea producătorului să emită SyntheticCP în operatorul de afișare a textului, iar cititorul consumator să rezolve SyntheticCP înapoi la GID prin /CIDToGIDMap la momentul randării

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - astfel încât calculatorul de reîncadrare a cuvintelor din v2.65 să găsească avansul hmtx corect pentru codepointul sintetic atunci când acesta apare în conținutul câmpurilor text AcroForm

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - tabela de reverse lookup per GID folosită de GetSyntheticCodepointForGID pentru a face apelurile repetate la AssignSyntheticCodepointForGID idempotente; al doilea apel cu același GID returnează deja codepointul SyntheticCP alocat

 

Returnează True la succes, cu SyntheticCP setat la codepointul alocat. Returnează False și lasă SyntheticCP la 0 în oricare dintre aceste condiții defensive: niciun font înregistrat (RegisterUnicodeTTF niciodată apelat sau apelat cu argumente goale pentru resetarea stării), GID invalid (zero sau peste numărul de glife din cmap), interval PUA epuizat (toate cele 6400 de sloturi U+E000 - U+F8FF alocate), cache neinițializat la intrare

 

Semantica GetSyntheticCodepointForGID

Interogare pur funcțională a oricărei atribuiri existente. Returnează codepointul sintetic alocat pentru GID dacă AssignSyntheticCodepointForGID(GID, ...) a fost apelată anterior; altfel returnează 0, care nu este un codepoint PUA valid și funcționează drept sentinelă pentru „fără atribuție”. Nu alocă nimic. Este sigur de apelat înainte ca vreun AssignSyntheticCodepointForGID să fi rulat

 

Ciclul de viață al stării alocatorului

FUnicodeSyntheticCpForGID și cursorul PUA următor disponibil (FUnicodeNextSyntheticCp) sunt alocate lazy la primul apel AssignSyntheticCodepointForGID. Cursorul pornește de la 0, neinițializat, și sare la $E000 la prima alocare; alocările ulterioare îl mută prin $E001, $E002, ..., $F8FF. Ambele câmpuri sunt resetate la gol / 0 la fiecare RegisterUnicodeTTF('', nil), împreună cu restul stării subsetului per font, astfel încât apelanții care refolosesc o instanță THotPDF pe mai multe documente pornesc fiecare document cu un cursor PUA proaspăt

 

Flux tipic (formă de cluster Devanagari)

 

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;

 

Exemplu de idempotentă

 

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)

 

Comportamentul cititorului consumator

Cititorul consumator vede codepointul PUA în operatorul de afișare a textului și îl rezolvă prin /CIDToGIDMap încorporat în document către GID-ul țintă, apoi redă acel GID folosind programul de font încorporat. Din perspectiva cititorului nu există nicio diferență între un codepoint Unicode „natural” pe care cmap-ul îl direcționează către GID și un codepoint sintetic PUA pe care /CIDToGIDMap îl direcționează către GID - ambele produc aceeași glifă redată

 

Comportamentul copy / paste: codepointurile PUA se întorc ca ele însele prin copy / paste când ToUnicode CMap le declară mapări identitate. Apelanții care doresc ca în schimb să se întoarcă la caracterele Unicode sursă (secvența de intrare care a produs substitutul) pot înregistra o mapare inversă cu RegisterToUnicodeReverseMapping sau pot autoriza proprietăți de secvență ActualText pentru conținut marcat prin BeginTaggedContent și pot emite codepointurile sintetice în conținutul încadrat. HotPDF folosește automat același model internal-CID pentru fluxurile de aparență AcroForm bazate pe RegisterUnicodeTTF care conțin caractere Unicode din plane suplimentare

 

Închiderea roadmap-ului Phase 8

v2.119.68 / Phase 8c.6 închide roadmap-ul motorului GSUB din Phase 8: fiecare API de interogare LookupType 1-8 (Phase 1-6), API-ul de selecție Script / LangSys (Phase 7), punctul de intrare pentru închiderea subsetter-ului TTF (Phase 9), plierea statică a ligaturilor în post-pass (v2.119.32 / 58 / 60 / 62), pipeline-ul automat opțional (v2.119.59), emisia automată Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), reverse-mapping-ul ToUnicode (v2.119.61 / 62 / 65), interogarea de avansare (v2.119.64), pre-pasul de reordonare Indic pentru Devanagari (v2.119.67) și acum emiterea la nivel GID a codepointului sintetic PUA (v2.119.68) se integrează toate într-o singură suprafață de formare pe partea producătorului care gestionează orice tip de glifă de substituție pe care o poate produce un font OpenType

 

Vezi și: Motorul de substituție OpenType GSUB, Fluxul automat de formare (Phase 8), Suport pentru formarea Arabic / Persian / Urdu, Formare Syriac / Mongolian / Devanagari, THotPDF.BeginTaggedContent