THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF PUA synthetic codepoint allocator (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

Asigna y consulta puntos de código sintéticos del Private Use Area (U+E000 - U+F8FF) para GID sustitutos OpenType GSUB que no tienen un punto de código Unicode natural accesible mediante el cmap de la fuente. Cierra la brecha de emisión de nivel GID del lado productor que dejaron las API de consulta y refinamiento GSUB de v2.119.43-66

 

Sintaxis Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Why the API exists

La canalización automática de shaping del lado productor de v2.119.32-67 (árabe / latín / devanagari) requiere que los GID sustitutos devueltos por el motor GSUB sean accesibles mediante un punto de código Unicode: la canalización de texto codificado en hexadecimal existente emite puntos de código, no GID, y el lector consumidor resuelve el punto de código de vuelta a un GID mediante el /CIDToGIDMap incrustado. Para GID sustitutos que tienen un punto de código Unicode natural mediante el cmap de la fuente (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), la canalización existente funciona correctamente

 

Pero los sustitutos específicos de fuente que terminan en GID internos de la fuente, como la mayoría de formas de clúster devanagari, alternativos estilísticos que el diseñador de la fuente entrega solo como GID numerados, secuencias de variación ideográfica CJK (IVS) y ligaduras discrecionales sin Presentation Form correspondiente, no tienen ningún punto de código en el cmap de la fuente. Antes de v2.119.68 estos GID eran inaccesibles mediante la canalización hexadecimal del lado productor; v2.119.68 cierra esa brecha permitiendo que los llamadores asignen un punto de código sintético en el Private Use Area para cualquier GID

 

Semántica de AssignSyntheticCodepointForGID

Asigna el siguiente punto de código PUA disponible (empezando en U+E000) para el GID suministrado y replica la asignación en cada caché de la que depende la canalización hexadecimal existente del lado productor + la cadena de resolución del lector consumidor:

 

1. FUnicodeCpToGid[SyntheticCP] := GID: para que la canalización hexadecimal del lado productor emita SyntheticCP en el operador de muestra de texto y el lector consumidor resuelva SyntheticCP de vuelta a GID mediante /CIDToGIDMap en tiempo de renderizado

2. FAcroFormUnicodeAdvances[SyntheticCP] := em-fraction: para que el calculador de ajuste de línea de v2.65 encuentre el avance hmtx correcto del punto de código sintético cuando aparece en contenido de campo de texto AcroForm

3. FUnicodeSyntheticCpForGID[GID] := SyntheticCP: tabla de búsqueda inversa por GID usada por GetSyntheticCodepointForGID para hacer idempotentes las llamadas repetidas a AssignSyntheticCodepointForGID (la segunda llamada con el mismo GID devuelve el SyntheticCP ya asignado)

 

Devuelve True al tener éxito, con SyntheticCP establecido en el punto de código asignado. Devuelve False (y deja SyntheticCP en 0) bajo cualquiera de estas condiciones defensivas: no hay fuente registrada (RegisterUnicodeTTF nunca se llamó o se llamó con argumentos vacíos para reiniciar el estado), GID no válido (cero o más allá del recuento de glifos del cmap), rango PUA agotado (las 6400 posiciones U+E000 - U+F8FF asignadas), caché no inicializada en la entrada

 

Semántica de GetSyntheticCodepointForGID

Consulta puramente funcional de cualquier asignación existente. Devuelve el punto de código sintético asignado para GID si AssignSyntheticCodepointForGID(GID, ...) se llamó previamente; de lo contrario devuelve 0 (que no es un punto de código PUA válido, por lo que también sirve como centinela de "sin asignación"). No asigna. Es seguro llamarlo antes de que se haya ejecutado cualquier AssignSyntheticCodepointForGID

 

Allocator state lifecycle

FUnicodeSyntheticCpForGID y el cursor del siguiente PUA disponible (FUnicodeNextSyntheticCp) se asignan de forma diferida en la primera llamada a AssignSyntheticCodepointForGID. El cursor empieza en 0 (sin inicializar) y salta a $E000 en la primera asignación; las asignaciones posteriores lo mueven por $E001, $E002, ..., $F8FF. Ambos campos se reinician a vacío / 0 en cada RegisterUnicodeTTF('', nil) junto con el resto del estado de subconjunto por fuente, de modo que los llamadores que reutilizan una instancia THotPDF en varios documentos empiezan cada documento con un cursor PUA nuevo

 

Flujo de trabajo típico (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 ahora está en el rango U+E000-F8FF; emitirlo

    // 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

El lector consumidor ve el punto de código PUA en el operador de muestra de texto y lo resuelve mediante el /CIDToGIDMap incrustado en el documento hacia el GID de destino, y luego renderiza ese GID usando el programa de fuente incrustado. Desde la perspectiva del lector no hay diferencia entre un punto de código Unicode "natural" que el cmap enruta a GID y un punto de código sintético PUA que /CIDToGIDMap enruta a GID: ambos producen el mismo glifo renderizado

 

Comportamiento de copiar / pegar: los puntos de código PUA hacen round-trip como sí mismos al copiar / pegar cuando el ToUnicode CMap los declara como mapeos de identidad. Los llamadores que quieran que los caracteres Unicode de origen (la secuencia de entrada que produjo el sustituto) hagan round-trip en su lugar pueden registrar un mapeo inverso con RegisterToUnicodeReverseMapping o crear propiedades de secuencia de contenido marcado ActualText mediante BeginTaggedContent y emitir los puntos de código sintéticos dentro del contenido entre corchetes. HotPDF usa automáticamente el mismo patrón CID interno para streams de apariencia AcroForm respaldados por RegisterUnicodeTTF que contienen caracteres Unicode de plano suplementario

 

Phase 8 roadmap closure

v2.119.68 / Phase 8c.6 cierra la hoja de ruta Phase 8 del motor GSUB: cada API de consulta LookupType 1-8 (Phase 1-6), la API de selección Script / LangSys (Phase 7), el punto de entrada de cierre del subsetter TTF (Phase 9), el plegado estático de ligaduras en post-pasada (v2.119.32 / 58 / 60 / 62), la canalización automática opcional (v2.119.59), la emisión automática árabe rlig + latina liga / clig + rclt (Phase 8b / 8c.2 / 8b / GSUB 'rclt'), el mapeo inverso ToUnicode (v2.119.61 / 62 / 65), la consulta de avance (v2.119.64), la pre-pasada de reordenación índica devanagari (v2.119.67) y ahora la emisión de nivel GID mediante punto de código sintético PUA (v2.119.68) se integran en una única superficie de shaping del lado productor que maneja todo tipo de glifo sustituto que una fuente OpenType puede producir

 

Véase también: Motor de sustitución OpenType GSUB, Canalización automática de modelado (fase 8), Soporte de modelado árabe / persa / urdu, Modelado siríaco / mongol / devanagari, THotPDF.BeginTaggedContent