THotPDF.AssignSyntheticCodepointForGID / GetSyntheticCodepointForGID

THotPDF asignador de codepoints sintéticos PUA (v2.119.68)

 

GSUB Engine  Auto Shaping Pipeline  Arabic Shaping

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

 

Sintaxis Delphi:

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

function GetSyntheticCodepointForGID(GID: Word): Word;

 

Por qué existe la API

La canalización automática del lado productor v2.119.32-67 (árabe / latín / devanagari) requiere que los GID sustitutos devueltos por el motor GSUB puedan alcanzarse mediante un codepoint Unicode: la canalización de texto codificada en hexadecimal existente emite codepoints, no GID, y el lector consumidor resuelve el codepoint de vuelta a un GID mediante /CIDToGIDMap incrustado. Para los GID sustitutos que sí tienen un codepoint Unicode natural a través del cmap de la fuente (Arabic Presentation Forms, Latin Standard Ligatures FB00-FB06), la canalización existente funciona bien

 

Pero los sustitutos específicos de la fuente que terminan en GID internos de la fuente - la mayoría de las formas de clúster devanagari, las alternas estilísticas que el diseñador de la fuente distribuye solo como GID numerados, las secuencias de variación ideográfica CJK (IVS), las ligaduras discrecionales sin Presentation Form correspondiente - no tienen ningún codepoint en el cmap de la fuente. Antes de v2.119.68 estos GID eran inalcanzables mediante la canalización hexadecimal del lado productor; v2.119.68 cierra esa brecha al permitir que quien llama asigne un codepoint sintético en el Private Use Area para cualquier GID

 

Semántica de AssignSyntheticCodepointForGID

Asigna el siguiente codepoint PUA disponible (comenzando en U+E000) para el GID proporcionado y replica la asignación en todas las cachés de las que depende la cadena de resolución de la canalización hexadecimal del lado productor + lector consumidor

 

1. FUnicodeCpToGid[SyntheticCP] := GID - para que la canalización hexadecimal del lado productor emita SyntheticCP en el operador de presentación 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 v2.65 encuentre el avance hmtx correcto para el codepoint sintético cuando aparece en contenido de campos de texto de AcroForm

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

 

Devuelve True si tiene éxito y deja SyntheticCP en el codepoint 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 restablecer el estado), GID inválido (cero o más allá del número de glifos del cmap), rango PUA agotado (los 6400 espacios U+E000 - U+F8FF ya asignados), caché sin inicializar al entrar

 

Semántica de GetSyntheticCodepointForGID

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

 

Ciclo de vida del estado del asignador

FUnicodeSyntheticCpForGID y el cursor del siguiente PUA disponible (FUnicodeNextSyntheticCp) se asignan bajo demanda en la primera llamada a AssignSyntheticCodepointForGID. El cursor comienza en 0 (sin inicializar) y pasa a $E000 en la primera asignación; las siguientes asignaciones lo llevan por $E001, $E002, ..., $F8FF. Ambos campos se restablecen a vacío / 0 en cada RegisterUnicodeTTF('', nil) junto con el resto del estado de subconjunto por fuente, de modo que quien reutiliza una instancia de THotPDF en varios documentos empieza cada documento con un cursor PUA nuevo

 

Flujo de trabajo típico (forma de clúster devanagari)

 

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;

 

Ejemplo de idempotencia

 

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)

 

Comportamiento del lector consumidor

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

 

Comportamiento de copiar y pegar: los codepoints PUA hacen ida y vuelta como ellos mismos en copiar y pegar cuando la CMap ToUnicode los declara como asignaciones de identidad. Los llamadores que en cambio quieran que hagan ida y vuelta los caracteres Unicode de origen (la secuencia de entrada que produjo el sustituto) pueden registrar un mapeo inverso con RegisterToUnicodeReverseMapping o definir propiedades de secuencia de contenido marcado ActualText mediante BeginTaggedContent y emitir los codepoints sintéticos dentro del contenido delimitado. HotPDF usa automáticamente el mismo patrón de CID interno para flujos de apariencia de AcroForm basados en RegisterUnicodeTTF que contienen caracteres Unicode de planos suplementarios

 

Cierre de la hoja de ruta de la fase 8

v2.119.68 / Phase 8c.6 cierra el recorrido del motor GSUB de la Fase 8: cada API de consulta LookupType 1-8 (Fases 1-6), la API de selección Script / LangSys (Fase 7), el punto de entrada de cierre del subconjunto TTF (Fase 9), el plegado estático de ligaduras en pospaso (v2.119.32 / 58 / 60 / 62), la canalización automática opcional (v2.119.59), la emisión automática de rlig árabe + liga / clig latinas + rclt (Fase 8b / 8c.2 / 8b / GSUB 'rclt'), el mapeo inverso de ToUnicode (v2.119.61 / 62 / 65), la consulta de avances (v2.119.64), el prepaso de reordenamiento Indic devanagari (v2.119.67) y ahora la emisión de GID con codepoint sintético PUA (v2.119.68) se integran en una sola superficie de modelado del lado productor que maneja cualquier tipo de glifo sustituto que pueda producir una fuente OpenType

 

Ver 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