|
THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID THotPDF PUA synthetic codepoint allocator (v2.119.68)
|
GSUB Engine Auto Shaping Pipeline Arabic Shaping |
|
Виділяє та запитує синтетичні кодові точки Private Use Area (U+E000 - U+F8FF) для гліфів GID заміни OpenType GSUB, які не мають природної кодової точки Unicode, досяжної через cmap шрифту; закриває пропуск виведення на рівні GID з боку генератора, залишений API запитів та уточнення GSUB версії v2.119.43-66
Синтаксис Delphi: function AssignSyntheticCodepointForGID(GID: Word; out SyntheticCP: Word): Boolean; function GetSyntheticCodepointForGID(GID: Word): Word;
Чому існує цей API Producer-side automatic shaping pipeline v2.119.32-67 (Arabic / Latin / Devanagari) потребує, щоб substitute GIDs, returned by GSUB engine, були reachable through Unicode codepoint - existing hex-encoded text pipeline emits codepoints, not GIDs, а consumer reader resolves codepoint back to GID через embedded /CIDToGIDMap Для substitute GIDs, що мають natural Unicode codepoint через cmap font (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), existing pipeline works fine
Але специфічні для шрифту заміни, які потрапляють на внутрішні GID шрифту — більшість форм кластерів деванагарі, стилістичні варіанти, які дизайнер шрифту постачає лише як пронумеровані GID, послідовності ідеографічних варіацій CJK (IVS), дискреційні лігатури без відповідної форми представлення — взагалі не мають кодової точки в cmap шрифту; до версії v2.119.68 ці GID були недосяжними через шістнадцятковий конвеєр з боку генератора, версія v2.119.68 закриває цей пропуск, дозволяючи викликачам виділяти синтетичну кодову точку в Private Use Area для будь-ного GID
Семантика AssignSyntheticCodepointForGID Виділяє наступну доступну кодову точку PUA (починаючи з U+E000) для наданого GID і дзеркально відображає призначення в кожен кеш, від якого залежить існуючий шістнадцятковий конвеєр з боку генератора та ланцюжок розв'язання переглядача споживача:
1. 2. 3.
Повертає True on success з SyntheticCP set to allocated codepoint Повертає False (і leaves SyntheticCP at 0) за будь-якої defensive condition: no font registered (RegisterUnicodeTTF never called або called with empty arguments to reset state), invalid GID (zero або beyond cmap glyph count), exhausted PUA range (all 6400 slots U+E000 - U+F8FF allocated), cache uninitialised on entry
Семантика GetSyntheticCodepointForGID Pure-functional query будь-якого existing assignment Повертає synthetic codepoint, allocated for GID, якщо AssignSyntheticCodepointForGID(GID, ...) викликали раніше; інакше returns 0 (not valid PUA codepoint, тому also sentinel «no assignment») Не allocate Безпечно call before any AssignSyntheticCodepointForGID has run
Життєвий цикл стану алокатора FUnicodeSyntheticCpForGID і cursor FUnicodeNextSyntheticCp створюються lazy під час першого AssignSyntheticCodepointForGID Cursor starts at 0 і під час першого allocation переходить до $E000; наступні allocations рухаються через $E001, $E002, ..., $F8FF Обидва fields reset to empty / 0 on every RegisterUnicodeTTF('', nil) разом із рештою per-font subset state, тому reused THotPDF instance починає кожен document з fresh PUA cursor
Типовий робочий процес (форма кластера деванагарі)
PDF.RegisterUnicodeTTF('NotoDeva', 'NotoSansDevanagari-Regular.ttf'); PDF.ShapingFeatures := [sfIndicShaping]; PDF.SetGSUBScript('deva');
// Отримання внутрішнього GID кластера шрифту через рушій GSUB 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;
Приклад ідемпотентності
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 бачить PUA codepoint у text-showing operator і resolves it through document-embedded /CIDToGIDMap to target GID, потім renders that GID using embedded font program З perspective reader немає difference між «natural» Unicode codepoint, який cmap routes to GID, і PUA synthetic codepoint, який /CIDToGIDMap routes to GID - both produce same rendered glyph
Поведінка copy / paste: PUA codepoints round-trip as themselves, коли ToUnicode CMap declares identity mappings Якщо callers хочуть round-trip source Unicode characters, що produced substitute, вони можуть register reverse mapping через RegisterToUnicodeReverseMapping або author ActualText marked-content properties through BeginTaggedContent і emit synthetic codepoints inside bracketed content HotPDF автоматично uses same internal-CID pattern для RegisterUnicodeTTF-backed AcroForm appearance streams з supplementary-plane Unicode characters
Закриття дорожньої карти фази 8 v2.119.68 / Phase 8c.6 завершує roadmap Phase 8 GSUB engine: query API LookupType 1-8, Script / LangSys selection API, TTF subsetter closure entry point, static post-pass ligature folding, opt-in automatic pipeline, автоматичне виведення Arabic rlig і Latin liga / clig / rclt, ToUnicode reverse-mapping, advance query, Devanagari Indic reorder pre-pass і PUA synthetic codepoint GID-level emit тепер інтегровано в єдину 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 |