THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Выделяет и запрашивает synthetic codepoints из Private Use Area (U+E000 - U+F8FF) для OpenType GSUB substitute GIDs, у которых нет естественного Unicode codepoint, достижимого через cmap шрифта. Закрывает producer-side GID-level emission gap, оставленный GSUB query и refinement APIs v2.119.43-66

 

Delphi syntax:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Why the API exists

Producer-side automatic shaping pipeline v2.119.32-67 (Arabic / Latin / Devanagari) требует, чтобы substitute GIDs, возвращенные GSUB engine, были достижимы через Unicode codepoint: существующий hex-encoded text pipeline выводит codepoints, а не GIDs, и consumer reader разрешает codepoint обратно в GID через embedded /CIDToGIDMap. Для substitute GIDs с естественным Unicode codepoint через cmap шрифта существующий pipeline работает нормально

 

Но font-specific substitutes, попадающие на font-internal GIDs — большинство Devanagari cluster shapes, stylistic alternates, которые designer шрифта поставляет только как numbered GIDs, CJK ideographic variation sequences (IVS), discretionary ligatures без Presentation Form — вообще не имеют codepoint в cmap шрифта. До v2.119.68 эти GIDs были недостижимы через producer-side hex pipeline; v2.119.68 закрывает пробел, позволяя callers выделять synthetic codepoint в Private Use Area для любого GID

 

AssignSyntheticCodepointForGID semantics

Выделяет следующий доступный PUA codepoint (начиная с U+E000) для указанного GID и зеркалирует assignment во все caches, от которых зависит существующая цепочка producer-side hex pipeline + consumer-reader resolution

 

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)

 

При успехе возвращает True и устанавливает SyntheticCP в выделенный codepoint. Возвращает False (оставляя SyntheticCP равным 0) при защитных условиях: font не зарегистрирован, GID недействителен, PUA range исчерпан или cache не инициализирован на входе

 

GetSyntheticCodepointForGID semantics

Чистый запрос любого существующего assignment. Возвращает synthetic codepoint, выделенный для GID, если AssignSyntheticCodepointForGID(GID, ...) уже вызывался; иначе возвращает 0, что не является допустимым PUA codepoint и служит sentinel «no assignment». Не выделяет. Безопасно до первого AssignSyntheticCodepointForGID

 

Allocator state lifecycle

FUnicodeSyntheticCpForGID и cursor next-available-PUA (FUnicodeNextSyntheticCp) lazy-allocates при первом вызове AssignSyntheticCodepointForGID. Cursor начинается с 0 (uninitialised), при первом allocation переходит к $E000, затем движется через $E001, $E002, ..., $F8FF. Оба поля сбрасываются на empty / 0 при каждом RegisterUnicodeTTF('', nil) вместе с остальным per-font subset state

 

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 behaviour

Consumer reader видит PUA codepoint в text-showing operator и разрешает его через document-embedded /CIDToGIDMap в target GID, затем рендерит этот GID встроенной font program. С точки зрения reader нет различия между natural Unicode codepoint, который cmap ведет к GID, и PUA synthetic codepoint, который /CIDToGIDMap ведет к GID

 

Поведение copy / paste: PUA codepoints round-trip как сами себя, когда ToUnicode CMap объявляет их identity mappings. Callers, которым нужен round-trip в исходные Unicode characters, могут зарегистрировать reverse mapping через RegisterToUnicodeReverseMapping или создать ActualText marked-content sequence properties через BeginTaggedContent и вывести synthetic codepoints внутри bracketed content

 

Phase 8 roadmap closure

v2.119.68 / Phase 8c.6 закрывает roadmap Phase 8 GSUB engine: LookupType 1-8 query API, Script / LangSys selection API, TTF subsetter closure entry point, static post-pass ligature folding, opt-in automatic pipeline, Arabic rlig + Latin liga / clig + rclt automatic emission, ToUnicode reverse-mapping, advance query, Devanagari Indic reorder pre-pass и теперь PUA synthetic codepoint GID-level emit интегрированы в одну producer-side shaping surface

 

См. также: OpenType GSUB Substitution Engine, Automatic Shaping Pipeline (Phase 8), Arabic / Persian / Urdu Shaping Support, Syriac / Mongolian / Devanagari Shaping, THotPDF.BeginTaggedContent