THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Aloca e consulta codepoints sintéticos da Private Use Area (U+E000 - U+F8FF) para GIDs substitutos GSUB do OpenType que não têm qualquer codepoint Unicode natural alcançável através do cmap do tipo de letra. Fecha a lacuna de emissão ao nível do GID do lado do produtor deixada pelas APIs de consulta e refinamento GSUB v2.119.43-66

 

Delphi syntax:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Why the API exists

O pipeline automático de formação do lado do produtor v2.119.32-67 (árabe / latina / devanagari) exige que os GIDs substitutos devolvidos pelo motor GSUB sejam alcançáveis através de um codepoint Unicode - o pipeline de texto em hexadecimal existente emite codepoints, não GIDs, e o leitor consumidor resolve o codepoint de volta para um GID através do /CIDToGIDMap incorporado. Para GIDs substitutos que tenham um codepoint Unicode natural via cmap do tipo de letra (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), o pipeline existente funciona bem

 

Mas os substitutos específicos da fonte que caem em GIDs internos da fonte - a maioria das formas de agrupamento Devanagari, alternates estilísticos que o designer da fonte fornece apenas como GIDs numerados, sequências de variação ideográfica CJK (IVS), ligaduras discricionárias sem Presentation Form correspondente - não têm qualquer codepoint no cmap da fonte. Antes do v2.119.68 estes GIDs eram inalcançáveis através do pipeline hex do lado do produtor; o v2.119.68 fecha essa lacuna ao permitir que os chamadores aloque um codepoint sintético na Private Use Area para qualquer GID

 

AssignSyntheticCodepointForGID semantics

Aloca o próximo codepoint PUA disponível (a começar em U+E000) para o GID fornecido e espelha a atribuição em todas as caches de que dependem o pipeline hex existente do lado do produtor + a cadeia de resolução do leitor consumidor:

 

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).

 

Devolve True em caso de sucesso com SyntheticCP definido para o codepoint alocado. Devolve False (e deixa SyntheticCP em 0) em qualquer uma destas condições defensivas: nenhum tipo de letra registado (RegisterUnicodeTTF nunca chamado ou chamado com argumentos vazios para repor o estado), GID inválido (zero ou além da contagem de glifos do cmap), intervalo PUA esgotado (todos os 6400 slots U+E000 - U+F8FF alocados), cache não inicializada à entrada

 

GetSyntheticCodepointForGID semantics

Consulta puramente funcional de qualquer atribuição existente. Devolve o codepoint sintético atribuído a GID se AssignSyntheticCodepointForGID(GID, ...) já tiver sido chamado; caso contrário devolve 0 (que não é um codepoint PUA válido, por isso também serve como sentinela de "sem atribuição"). Não aloca nada. É seguro chamar antes de qualquer AssignSyntheticCodepointForGID

 

Allocator state lifecycle

FUnicodeSyntheticCpForGID e o cursor PUA seguinte disponível (FUnicodeNextSyntheticCp) são alocados preguiçosamente na primeira chamada de AssignSyntheticCodepointForGID. O cursor começa em 0 (não inicializado) e avança para $E000 na primeira alocação; as alocações seguintes movem-no através de $E001, $E002, ..., $F8FF. Ambos os campos são repostos para vazio / 0 em cada RegisterUnicodeTTF('', nil), juntamente com o resto do estado de subconjunto por tipo de letra, para que chamadores que reutilizem uma instância de THotPDF em vários documentos comecem cada documento com um cursor PUA novo

 

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

O leitor consumidor vê o codepoint PUA no operador de apresentação de texto e resolve-o através do /CIDToGIDMap incorporado no documento para o GID alvo, depois desenha esse GID usando o programa de tipo de letra incorporado. Do ponto de vista do leitor, não há diferença entre um codepoint Unicode "natural" que a cmap encaminha para GID e um codepoint sintético PUA que /CIDToGIDMap encaminha para GID - ambos produzem o mesmo glifo renderizado

 

Comportamento de copiar / colar: os codepoints PUA fazem round-trip como eles próprios através de copiar / colar quando o ToUnicode CMap os declara como mapeamentos de identidade. Os chamadores que pretendam que os caracteres Unicode de origem (a sequência de entrada que produziu o substituto) façam round-trip em vez disso podem registar um mapeamento inverso com RegisterToUnicodeReverseMapping ou criar propriedades de sequência de conteúdo marcado ActualText através de BeginTaggedContent e emitir os codepoints sintéticos dentro do conteúdo entre parênteses. O HotPDF usa automaticamente o mesmo padrão interno de CID para fluxos de aparência AcroForm com base em RegisterUnicodeTTF que contenham caracteres Unicode do plano suplementar

 

Phase 8 roadmap closure

v2.119.68 / Fase 8c.6 fecha a folha de rota do motor GSUB da Fase 8: todas as APIs de consulta LookupType 1-8 (Fases 1-6), a API de selecção Script / LangSys (Fase 7), o ponto de entrada de fecho do subsetter TTF (Fase 9), o pregueamento estático pós-passagem de ligaduras (v2.119.32 / 58 / 60 / 62), o pipeline automático opcional (v2.119.59), a emissão automática de rlig árabe + liga / clig latinas + rclt (Fase 8b / 8c.2 / 8b / GSUB 'rclt'), o remapeamento inverso ToUnicode (v2.119.61 / 62 / 65), a consulta de avanço (v2.119.64), o pré-passo de reordenação Indic do devanagari (v2.119.67) e agora a emissão ao nível de GID de codepoints sintéticos PUA (v2.119.68) integram-se todos numa única superfície de formação do lado do produtor que trata de todos os tipos de glifo substituto que um tipo de letra OpenType pode produzir

 

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