|
Motor de sustitución OpenType GSUB Superficie de capacidad de sustitución de glifos (v2.119.43 - v2.119.50)
|
Arabic Shaping CFF / OpenType Subsetting |
|
El motor GSUB (Glyph SUBstitution) de OpenType integrado en HotPDF permite consultar, dirigir e incrustar todos los tipos de sustitución de glifos que declara una fuente OpenType: ligaduras, alternativas estilísticas, variantes contextuales, formas de shaping árabe / índico, formas alternativas CJK, etc. Todos los LookupType 1 a 8 de GSUB de OpenType están implementados y expuestos como una superficie de consulta solo de capacidad; quien llama dirige la emisión del texto y decide qué glifo sustituto escribir en el flujo de contenido de la página.
API pública type TGSUBStringArray = array of AnsiString;
// LookupType 1 - Single Substitution (one glyph -> one glyph) function GetSingleSubstituteGlyph(InputGID: Word; const FeatureTag: AnsiString): Word;
// LookupType 2 - Multiple Substitution (one glyph -> sequence of glyphs) function GetMultipleSubstituteGlyphs(InputGID: Word; const FeatureTag: AnsiString; var OutGIDs: array of Word): Boolean;
// LookupType 3 - Alternate Substitution (one glyph -> one of N alternates) function GetAlternateGlyphCount(InputGID: Word; const FeatureTag: AnsiString): Integer; function GetAlternateGlyph(InputGID: Word; const FeatureTag: AnsiString; AlternateIndex: Integer): Word;
// LookupType 4 - Ligature Substitution (N glyphs -> one ligature) function ApplyLigatureSubstitution(const InputGIDs: array of Word; StartIndex: Integer; const FeatureTag: AnsiString; out OutGID: Word; out ConsumedCount: Integer): Boolean;
// LookupType 5 + 6 - Sustitución contextual / contextual encadenada function ApplyContextualSubst(const InputGIDs: array of Word; StartIndex: Integer; const FeatureTag: AnsiString; var OutGIDs: array of Word; out ConsumedLen: Integer): Boolean;
// LookupType 8 - Sustitución simple contextual inversa encadenada function ApplyReverseChainedContextualSubst(const InputGIDs: array of Word; StartIndex: Integer; const FeatureTag: AnsiString; out OutGID: Word): Boolean;
// Selección de Script / LangSys (fase 7) procedure SetGSUBScript(const ScriptTag: AnsiString); procedure SetGSUBLanguage(const LangTag: AnsiString); function GetGSUBScripts: TGSUBStringArray; function GetGSUBLanguages(const ScriptTag: AnsiString): TGSUBStringArray; function GetGSUBFeatures(const ScriptTag, LangTag: AnsiString): TGSUBStringArray;
// Cierre del subsetter TTF (fase 9) procedure MarkUnicodeGlyphUsed(GID: Word);
Descripción El motor se activa después de que
Contrato defensivo de principio a fin: las fuentes sin tabla GSUB, las etiquetas de funcionalidad de 4 bytes no estándar, las funcionalidades que el script / idioma seleccionado no anuncia, los GID que ninguna subtabla cubre y los glifos de entrada ignorados por LookupFlag devuelven todos un no-op seguro (False / OutGID = InputGID / OutGIDs vacío / ConsumedCount = 1) para que los llamadores nunca vean excepciones en los casos rutinarios de "no hay sustitución aplicable".
Matriz de LookupTypes LookupType 1 (Single Substitution) - un glifo se mapea a un sustituto. Funcionalidades canónicas: LookupType 2 (Multiple Substitution) - un glifo se divide en una secuencia de glifos sustitutos. Usuario canónico: LookupType 3 (Alternate Substitution) - un glifo se mapea a una de N alternates. Características canónicas: LookupType 4 (Ligature Substitution) - N glifos de entrada se pliegan en una ligadura. Características canónicas: LookupType 5 (Contextual Substitution) + LookupType 6 (Chained Contextual Substitution) - hacen coincidir una secuencia de glifos de entrada y despachan lookups anidados en posiciones concretas dentro de la coincidencia. Se implementan las tres variantes de Format (1 secuencia literal, 2 secuencia ClassDef, 3 secuencia Coverage); el despachador de SequenceLookupRecord vuelve a entrar en LookupList y gestiona lookups anidados Single / Multiple / Alternate (first) / Ligature con seguimiento en vivo de MatchPositions. Features canónicas: LookupType 7 (Extension Substitution) - capa de pura indirección que la especificación OpenType define para fuentes cuya subtabla de sustitución vive más allá del alcance de 16 bits del LookupList. Toda API pública sigue de forma transparente la indirección Offset32 de 32 bits hacia la subtabla real LookupType 1 / 2 / 3 / 4 / 5 / 6 / 8. Desbloquea fuentes CJK / índicas pesadas (Noto Sans CJK, Noto Sans Devanagari) cuyo GSUB supera los 64 KB. Sin API separada: el desenvuelto es automático. LookupType 8 (Reverse Chained Contextual Single Substitution) - sustitución 1:1 sensible al contexto cuya particularidad es que quien llama debe aplicarla en orden de recorrido INVERSO sobre una tirada de varios glifos (final -> inicio), porque cada sustituto puede depender de un contexto de lookahead FUTURO que aún no debe haber sido sustituido. Uso canónico: alternativas contextuales de árabe / siríaco / N'Ko / índico cuya forma final depende del glifo siguiente. Use
Selección de Script / LangSys Por defecto el motor prefiere el script
Semántica estricta frente a fallback: un
Respeto de LookupFlag y GDEF Cada consulta lee el LookupFlag de cada tabla Lookup (y el uint16 opcional markFilteringSet final cuando
Cierre del subsetter TTF (MarkUnicodeGlyphUsed) El subsetter TTF v2.84.0 de HotPDF deriva su conjunto de glifos usados de
Tras emitir cualquier GID devuelto por
Flujo típico (versalitas latinas)
PDF.RegisterUnicodeTTF('myFont', 'C:\\Windows\\Fonts\\arial.ttf'); PDF.SetGSUBScript('latn'); PDF.SetGSUBLanguage(''); // default LangSys SmallCapGID := PDF.GetSingleSubstituteGlyph(InputGID, 'smcp'); if SmallCapGID <> InputGID then begin emite SmallCapGID en el content stream de la página... PDF.MarkUnicodeGlyphUsed(SmallCapGID); // pull into subset end;
Flujo típico (ligadura árabe LAM-ALEF)
PDF.SetGSUBScript('arab'); Run := [LamGID, FathaGID, AlefGID]; // post-cmap GIDs if PDF.ApplyLigatureSubstitution(Run, 0, 'rlig', LigGID, ConsumedCount) then begin emite LigGID + avanza ConsumedCount PDF.MarkUnicodeGlyphUsed(LigGID); end;
Alcance y limitaciones El motor es una superficie de consulta solo de capacidades: responde a «qué haría GSUB aquí», pero no ejecuta un pipeline de shaping automático (layout tipo Harfbuzz, reordenado consciente de clústeres para índico, resolución BiDi, posicionamiento GPOS, anclaje de marcas). Los llamadores son responsables de dirigir el bucle de escaneo, elegir qué sustituto / alternate emitir, llamar a
El shaping árabe / persa / urdu en el lado del productor (ligadura obligatoria LAM-ALEF + Arabic Presentation Forms-A) está implementado como un pipeline integrado separado que se ejecuta automáticamente durante la emisión de texto; consulte Shaping árabe / persa / urdu.
Trazado de versiones v2.119.43 Single Substitution + Fase 1. v2.119.44 Multiple + Alternate (Fase 2). v2.119.45 Ligature (Fase 3). v2.119.46 Extension + GDEF + respeto de LookupFlag (Fase 4). v2.119.47 Contextual + Chained Contextual + despachador de SequenceLookupRecord (Fase 5). v2.119.48 Reverse Chained Contextual - matriz LookupType 1-8 cerrada (Fase 6). v2.119.49 API de selección de Script / LangSys (Fase 7). v2.119.50 clausura del subsetter TTF mediante
Véase también: Arabic / Persian / Urdu Shaping, CFF / OpenType Font Subsetting Functions, THotPDF.EnableFontSubsetting |