THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF alokator syntetycznych punktów kodowych PUA (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Alokuje i odpytuje syntetyczne punkty kodowe Private Use Area (U+E000 - U+F8FF) dla zastępczych GID OpenType GSUB, które nie mają naturalnego punktu kodowego Unicode osiągalnego przez cmap fontu. Zamyka lukę emisji na poziomie GID po stronie producenta pozostawioną przez API zapytań i doprecyzowania GSUB v2.119.43-66

 

Delphi syntax:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Dlaczego API istnieje

Automatyczny potok kształtowania po stronie producenta v2.119.32-67 (Arabic / Latin / Devanagari) wymaga, aby zastępcze GID zwrócone przez silnik GSUB były osiągalne przez punkt kodowy Unicode - istniejący potok tekstu kodowanego szesnastkowo emituje punkty kodowe, nie GID, a czytnik konsumencki rozwiązuje punkt kodowy z powrotem do GID przez osadzony /CIDToGIDMap. Dla zastępczych GID, które mają naturalny punkt kodowy Unicode przez cmap fontu (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), istniejący potok działa poprawnie

 

Jednak substytuty specyficzne dla fontu, które trafiają na wewnętrzne GID fontu - większość kształtów klastrów Devanagari, warianty stylistyczne dostarczone przez projektanta fontu tylko jako numerowane GID, sekwencje wariantów ideograficznych CJK (IVS), ligatury uznaniowe bez odpowiadającej im Presentation Form - w ogóle nie mają punktu kodowego w cmap fontu. Przed v2.119.68 te GID były nieosiągalne przez potok hex po stronie producenta; v2.119.68 zamyka tę lukę, pozwalając wywołującym alokować syntetyczny punkt kodowy w Private Use Area dla dowolnego GID

 

Semantyka AssignSyntheticCodepointForGID

Alokuje następny dostępny punkt kodowy PUA (zaczynając od U+E000) dla podanego GID i odzwierciedla przypisanie w każdej pamięci podręcznej, od której zależy istniejący łańcuch potoku hex po stronie producenta + rozwiązywania przez czytnik konsumencki:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - so the producer-side hex pipeline emits SyntheticCP into the text-showing operator and the consumer reader resolves SyntheticCP back to GID through /CIDToGIDMap at render time

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction - so the v2.65 word-wrap calculator finds the correct hmtx advance for the synthetic codepoint when it appears in AcroForm text-field content

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP - the per-GID reverse-lookup table used by GetSyntheticCodepointForGID to make repeat AssignSyntheticCodepointForGID calls idempotent (the second call with the same GID returns the already-allocated SyntheticCP)

 

Zwraca True po powodzeniu, ustawiając SyntheticCP na przydzielony punkt kodowy. Zwraca False (i pozostawia SyntheticCP równe 0) w dowolnym z tych warunków obronnych: brak zarejestrowanego fontu (RegisterUnicodeTTF nigdy nie wywołano lub wywołano z pustymi argumentami w celu zresetowania stanu), nieprawidłowy GID (zero albo poza liczbą glifów cmap), wyczerpany zakres PUA (wszystkie 6400 slotów U+E000 - U+F8FF przydzielone), pamięć podręczna niezainicjowana przy wejściu

 

Semantyka GetSyntheticCodepointForGID

Czyste zapytanie funkcyjne o istniejące przypisanie. Zwraca syntetyczny punkt kodowy przydzielony dla GID, jeśli AssignSyntheticCodepointForGID(GID, ...) wywołano wcześniej; w przeciwnym razie zwraca 0 (nie jest to prawidłowy punkt kodowy PUA, więc działa także jako strażnik „brak przypisania”). Nie alokuje. Można bezpiecznie wywołać przed pierwszym uruchomieniem AssignSyntheticCodepointForGID

 

Cykl życia stanu alokatora

FUnicodeSyntheticCpForGID i kursor następnego dostępnego PUA (FUnicodeNextSyntheticCp) są alokowane leniwie przy pierwszym wywołaniu AssignSyntheticCodepointForGID. Kursor zaczyna od 0 (niezainicjowany) i przechodzi do $E000 przy pierwszej alokacji; kolejne alokacje przesuwają go przez $E001, $E002, ..., $F8FF. Oba pola są resetowane do pustych / 0 przy każdym RegisterUnicodeTTF('', nil) razem z resztą stanu podzbioru per font, więc wywołujący ponownie używający instancji THotPDF w wielu dokumentach zaczynają każdy dokument ze świeżym kursorem PUA

 

Typical workflow (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)

 

Zachowanie czytnika konsumenckiego

Czytnik konsumencki widzi punkt kodowy PUA w operatorze wyświetlania tekstu i rozwiązuje go przez osadzony w dokumencie /CIDToGIDMap do docelowego GID, a następnie renderuje ten GID przy użyciu osadzonego programu fontu. Z perspektywy czytnika nie ma różnicy między „naturalnym” punktem kodowym Unicode, który cmap kieruje do GID, a syntetycznym punktem kodowym PUA, który /CIDToGIDMap kieruje do GID - oba tworzą ten sam renderowany glif

 

Zachowanie kopiowania / wklejania: punkty kodowe PUA przechodzą przez kopiowanie / wklejanie jako one same, gdy ToUnicode CMap deklaruje je jako mapowania tożsamościowe. Wywołujący, którzy zamiast tego chcą zachować znaki Unicode źródła (wejściowy przebieg, który wytworzył substytut), mogą zarejestrować mapowanie odwrotne przez RegisterToUnicodeReverseMapping albo zapisać właściwości sekwencji marked-content ActualText przez BeginTaggedContent i wyemitować syntetyczne punkty kodowe wewnątrz treści w nawiasach. HotPDF automatycznie używa tego samego wzorca internal-CID dla strumieni wyglądu AcroForm opartych na RegisterUnicodeTTF, które zawierają znaki Unicode z płaszczyzn dodatkowych

 

Domknięcie mapy drogowej Phase 8

v2.119.68 / Phase 8c.6 domyka mapę drogową silnika GSUB Phase 8: wszystkie API zapytań LookupType 1-8 (Phase 1-6), API wyboru Script / LangSys (Phase 7), punkt domknięcia subsettera TTF (Phase 9), statyczne składanie ligatur w post-pass (v2.119.32 / 58 / 60 / 62), opcjonalny potok automatyczny (v2.119.59), automatyczna emisja Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), mapowanie odwrotne ToUnicode (v2.119.61 / 62 / 65), zapytanie o advance (v2.119.64), pre-pass zmiany kolejności Devanagari Indic (v2.119.67), a teraz także emisja syntetycznych punktów kodowych PUA na poziomie GID (v2.119.68) integrują się w jedną powierzchnię kształtowania po stronie producenta, która obsługuje każdy rodzaj glifu zastępczego możliwy do wytworzenia przez font OpenType

 

Zobacz też: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Arabic / Persian / Urdu Shaping Support, Syriac / Mongolian / Devanagari Shaping, THotPDF.BeginTaggedContent