THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Allocates and queries Private Use Area (U+E000 - U+F8FF) synthetic codepoints за OpenType GSUB substitute GID-ове, които нямат естествен Unicode codepoint, достижим през cmap на шрифта. Затваря producer-side GID-level emission gap-а, оставен от v2.119.43-66 GSUB query и refinement API-те

 

Delphi syntax:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Why the API exists

Производственият конвейер за автоматичен шейпинг във v2.119.32-67 (Arabic / Latin / Devanagari) изисква заместителните GID, върнати от GSUB двигателя, да бъдат достижими чрез Unicode кодова точка - съществуващият pipeline за hex-кодиране изхвърля кодови точки, не GID, а четецът връща кодовата точка обратно към GID през вградения /CIDToGIDMap. За заместителни GID с естествена Unicode кодова точка през cmap на шрифта (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), съществуващият конвейер работи нормално

 

Но font-specific заместители, които попадат върху font-internal GID - повечето Devanagari cluster shapes, stylistic alternates, които дизайнерът на шрифта доставя само като номерирани GID, CJK ideographic variation sequences (IVS), discretionary ligatures без съответстваща Presentation Form - изобщо нямат codepoint в cmap на шрифта. Преди v2.119.68 тези GID-ове бяха недостижими през producer-side hex pipeline-а; v2.119.68 затваря тази празнина, като позволява на извикващите да заделят synthetic codepoint в Private Use Area за всеки GID

 

AssignSyntheticCodepointForGID semantics

Заделя следващия наличен PUA codepoint (започвайки от U+E000) за подадения GID и оглежда присвояването във всеки cache, от който зависи съществуващата producer-side hex pipeline + consumer-reader resolution chain:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - така producer-side hex pipeline-ът излъчва SyntheticCP в text-showing operator-а, а consumer reader-ът връща SyntheticCP обратно към GID през /CIDToGIDMap при render време

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 - per-GID reverse-lookup таблицата, използвана от GetSyntheticCodepointForGID, за да направи повторните AssignSyntheticCodepointForGID извиквания идемпотентни (второто извикване със същия GID връща вече заделения SyntheticCP)

 

Връща True при успех, като SyntheticCP се задава на разпределения codepoint. Връща False (и оставя SyntheticCP на 0) при някое от тези защитни условия: няма регистриран шрифт (RegisterUnicodeTTF не е извикан или е извикан с празни аргументи за нулиране на state), invalid GID (нула или извън броя glyph-ове на cmap-а), PUA range изчерпан (всички 6400 слота U+E000 - U+F8FF са разпределени), cache неинициализиран при вход

 

GetSyntheticCodepointForGID semantics

Pure-functional заявка за всяко съществуващо присвояване. Връща synthetic codepoint, заделен за GID, ако AssignSyntheticCodepointForGID(GID, ...) е била извикана преди това; в противен случай връща 0 (което не е валиден PUA codepoint и служи и като sentinel за "без присвояване"). Не заделя нищо. Безопасно е да се извика преди да е изпълнен какъвто и да е AssignSyntheticCodepointForGID

 

Allocator state lifecycle

FUnicodeSyntheticCpForGID и next-available-PUA cursor-ът (FUnicodeNextSyntheticCp) се заделят lazy при първото AssignSyntheticCodepointForGID извикване. Cursor-ът започва от 0 (uninitialised) и скача до $E000 при първото присвояване; следващите присвоявания го местят през $E001, $E002, ..., $F8FF. И двете полета се нулират до empty / 0 при всяко RegisterUnicodeTTF('', nil) заедно с останалия per-font subset state, така че извикващите, които преизползват THotPDF instance през няколко документа, започват всеки документ с fresh PUA cursor

 

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)

 

Consumer-reader behavior

Потребителският четец вижда PUA кодовата точка в оператора за показване на текст и я връща през вградения в документа /CIDToGIDMap към целевия GID, после визуализира този GID чрез вградената програма на шрифта. От гледна точка на читателя няма разлика между "естествена" Unicode кодова точка, която cmap насочва към GID, и PUA синтетична кодова точка, която /CIDToGIDMap насочва към GID - и двете произвеждат една и съща визуализирана графема

 

Copy / paste behavior: PUA codepoints round-trip-ват като самите себе си през copy / paste, когато ToUnicode CMap ги декларира като identity mappings. Извикващите, които искат source Unicode знаците (input run-ът, произвел substitute-а) да round-trip-нат вместо това, могат да регистрират reverse mapping с RegisterToUnicodeReverseMapping или да авторират ActualText marked-content sequence properties през BeginTaggedContent и да излъчат synthetic codepoint-ите вътре в bracketed content-а. HotPDF използва същия internal-CID pattern автоматично за RegisterUnicodeTTF-backed AcroForm appearance streams, които съдържат supplementary-plane Unicode знаци

 

Phase 8 roadmap closure

v2.119.68 / Phase 8c.6 closes the Phase 8 GSUB engine roadmap: every LookupType 1-8 query API (Phase 1-6), Script / LangSys selection API (Phase 7), TTF subsetter closure entry point (Phase 9), static post-pass ligature folding (v2.119.32 / 58 / 60 / 62), opt-in automatic pipeline (v2.119.59), Arabic rlig + Latin liga / clig + rclt automatic emission (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), ToUnicode reverse-mapping (v2.119.61 / 62 / 65), advance query (v2.119.64), Devanagari Indic reorder pre-pass (v2.119.67) и сега PUA synthetic codepoint GID-level emit (v2.119.68) се интегрират в единен producer-side shaping surface, който обработва всеки вид substitute glyph, който OpenType font може да произведе

 

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