THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF Alocador de codepoint sintético PUA (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 OpenType GSUB que não têm codepoint Unicode natural acessível pelo cmap da fonte. Fecha a lacuna de emissão em nível de GID do produtor deixada pelas APIs GSUB de consulta e refinamento da v2.119.43-66

 

Sintaxe Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Por que a API existe

O pipeline automático de shaping no produtor da v2.119.32-67 (Arabic / Latin / Devanagari) exige que GIDs substitutos retornados pelo mecanismo GSUB sejam acessíveis por um codepoint Unicode; o pipeline de texto hex-encoded existente emite codepoints, não GIDs, e o leitor consumidor resolve o codepoint de volta para um GID pelo /CIDToGIDMap incorporado. Para GIDs substitutos que têm um codepoint Unicode natural via cmap da fonte (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), o pipeline existente funciona corretamente

 

Mas substitutos específicos da fonte que vivem em GIDs internos da fonte — a maioria das formas de cluster 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 codepoint algum no cmap da fonte. Antes da v2.119.68, esses GIDs eram inalcançáveis pelo pipeline hex do produtor; a v2.119.68 fecha essa lacuna permitindo que os chamadores aloquem um codepoint sintético na Private Use Area para qualquer GID

 

Semântica do AssignSyntheticCodepointForGID

Aloca o próximo codepoint PUA disponível (começando em U+E000) para o GID fornecido e espelha a atribuição em todos os caches dos quais a cadeia existente pipeline hex do produtor + resolução do leitor consumidor depende:

 

1. FUnicodeCpToGid[SyntheticCP] := GID - so the producer-side hex pipeline emits SyntheticCP into the text-showing operator e 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).

 

Retorna True em caso de sucesso, com SyntheticCP definido para o codepoint alocado. Retorna False (e deixa SyntheticCP em 0) sob qualquer uma destas condições defensivas: nenhuma fonte registrada (RegisterUnicodeTTF nunca chamado ou chamado com argumentos vazios para redefinir 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 inicializado na entrada

 

Semântica do GetSyntheticCodepointForGID

Consulta puramente funcional de qualquer alocação existente. Retorna o codepoint sintético alocado para GID if AssignSyntheticCodepointForGID(GID, ...) has been called previously; otherwise returns 0 (which is not a valid PUA codepoint, so it doubles as a "no assignment" sentinel). Does not allocate. Safe to call before any AssignSyntheticCodepointForGID has run.

 

Ciclo de vida do estado do alocador

FUnicodeSyntheticCpForGID e o cursor de próxima PUA disponível (FUnicodeNextSyntheticCp) são alocados preguiçosamente na primeira chamada AssignSyntheticCodepointForGID. O cursor começa em 0 (não inicializado) e avança para $E000 na primeira alocação; alocações seguintes o movem por $E001, $E002, ..., $F8FF. Ambos os campos são redefinidos para vazio / 0 em todo RegisterUnicodeTTF('', nil) junto do restante do estado de subconjunto por fonte, para que chamadores que reutilizam uma instância THotPDF em vários documentos iniciem cada documento com um cursor PUA novo

 

Fluxo de trabalho típico (forma de cluster Devanágari)

 

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

  // Verifica se o cmap alcança o substituto - geralmente não para os

  // clusters Índicos, pois GIDs de cluster são internos da fonte

  // Aloca um codepoint sintético que o lado do produtor

  // pipeline hex pode emitir

  if PDF.AssignSyntheticCodepointForGID(ClusterGID, SyntheticCP) then

  begin

    // SyntheticCP está agora na faixa U+E000-F8FF; o emita

    // através do UnicodeTextOut assim como um codepoint normal

    PDF.CurrentPage.UnicodeTextOut(X, Y, 0, UnicodeChar(SyntheticCP));

    PDF.MarkUnicodeGlyphUsed(ClusterGID);

  end;

end;

 

Exemplo de idempotência

 

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 (nenhuma alocação)

 

Comportamento do leitor consumidor

O leitor consumidor vê o codepoint PUA no operador de exibição de texto e o resolve pelo /CIDToGIDMap incorporado no documento para o GID alvo, depois renderiza esse GID usando o programa de fonte incorporado. Do ponto de vista do leitor, não há diferença entre um codepoint Unicode "natural" que o cmap roteia para GID e um codepoint PUA sintético que /CIDToGIDMap roteia para GID; ambos produzem o mesmo glifo renderizado

 

Comportamento de Copiar / Colar: codepoints PUA viajam como eles mesmos através de copiar / colar quando o ToUnicode CMap os declara como mapeamentos de identidade. Chamadores que desejam ida e volta dos caracteres Unicode de origem (a execução de entrada que produziu o substituto) podem registrar um mapeamento reverso com RegisterToUnicodeReverseMapping ou criar propriedades de sequência marked-content ActualText por meio de BeginTaggedContent e emitir os codepoints sintéticos dentro do conteúdo entre colchetes. O HotPDF usa automaticamente o mesmo padrão de CID interno para fluxos de aparência AcroForm baseados em RegisterUnicodeTTF que contêm caracteres Unicode do plano suplementar

 

Encerramento do roteiro da Fase 8

v2.119.68 / Fase 8c.6 conclui o roteiro do mecanismo GSUB da Fase 8: todas as APIs de consulta LookupType 1-8 (Fase 1-6), a API de seleção Script / LangSys (Fase 7), o ponto de entrada de fechamento de subconjunto TTF (Fase 9), o dobramento estático pós-passagem de ligaduras (v2.119.32 / 58 / 60 / 62), o pipeline automático opcional (v2.119.59), emissão automática Arabic rlig + Latin liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), mapeamento reverso ToUnicode (v2.119.61 / 62 / 65), consulta de avanço (v2.119.64), pré-passagem de reordenação Indic Devanagari (v2.119.67) e agora emissão em nível de GID por codepoint sintético PUA (v2.119.68) se integram em uma única superfície de shaping no produtor que cobre todo tipo de glifo substituto que uma fonte OpenType pode produzir

 

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