Suporte a shaping árabe / persa / urdu

Pipeline de shaping no lado do produtor (v2.85.0 - v2.119.68)

 

OpenType GSUB Engine  Subsetting CFF / OpenType

O HotPDF roda um pipeline de shaping no lado do produtor que dobra runs árabe, persa e urdu de entrada Unicode em suas Arabic Presentation Forms durante a emissão de texto PDF, de modo que leitores consumidores recebam glifos posicionais / de ligadura prontos para renderizar sem precisar de um shaper classe Harfbuzz próprio.

 

O que o pipeline faz

Positional shaping (v2.85.0): cada letra árabe base tem até quatro formas posicionais — isolated (isol), initial (init), medial (medi), final (fina). O HotPDF inspeciona a classe de ligação de cada caractere árabe e as classes de ligação dos vizinhos imediatos, e depois mapeia o codepoint de entrada ao glifo Arabic Presentation Forms-B apropriado (U+FE70 - U+FEFC) antes da emissão. Letras sem ligação, juntadores, caracteres transparentes (combining marks) e o kashida Tatweel são todos tratados conforme o algoritmo Unicode Arabic Shaping.

 

LAM-ALEF mandatory ligature (v2.119.32): a spec Unicode Arabic Shaping exige que qualquer LAM (U+0644) imediatamente seguida de uma ALEF (U+0627 simples, U+0622 com madda acima, U+0623 com hamza acima, U+0625 com hamza abaixo) se funda em um único glifo de ligadura (U+FEFB - U+FEFC formas isolated / final com variantes apropriadas de hamza / madda). Esta é uma das pouquíssimas ligaduras não opcionais da tipografia árabe e é exigida para correção; renderizá-las como glifos separados produz texto que leitores nativos reconhecem imediatamente como malformado. O HotPDF executa a fusão durante a emissão, de modo que os chamadores não precisem de um shaper classe Harfbuzz no próprio caminho de código deles.

 

Persian / Urdu core 9 letters (v2.119.35): persa e urdu estendem o árabe com letras que não estão no bloco Arabic Presentation Forms-B (U+FE70 - U+FEFC). As 9 letras mais usadas desse tipo — incluindo PEH (U+067E), TCHEH (U+0686), JEH (U+0698), KEH (U+06A9 / U+06AF), GAF (U+06AF), NOON GHUNNA (U+06BA), HEH DOACHASHMEE (U+06BE), YEH BARREE (U+06D2) e HEH GOAL (U+06C1) — têm presentation forms em Arabic Presentation Forms-A (U+FB50 - U+FDFF). O HotPDF agora mapeia essas letras ao glifo Forms-A apropriado durante o shaping posicional, de modo que texto persa e urdu renderize com as formas init / medi / fina / isol corretas em qualquer leitor consumidor.

 

Arabic Extended-A + Supplement (v2.119.52, v2.119.56): a tabela de classes de ligação agora cobre os caracteres restantes do Arabic Extended-A (variantes de ALEF WASLA / NOON GHUNNA / HEH), o Arabic Supplement U+0750-U+077F e a faixa superior do Arabic Extended-A U+08A0-U+08FF. Caracteres com codificação estática em Presentation Forms-A são mapeados pelo shaper existente de 4 posições; caracteres sem ela (a maior parte do Extended-A) recebem apenas a classificação de classe de ligação, para que os vizinhos façam shaping corretamente mesmo quando o próprio caractere passa inalterado. A v2.119.56 corrigiu dois mapeamentos Forms-A errados introduzidos pela v2.119.52 (U+06C2 / U+06C3).

 

Persian / Urdu Form-B full coverage (v2.119.57): a tabela de classes de ligação foi estendida para cobrir toda a faixa U+0672-U+06D5 (cerca de 80 caracteres cobrindo variantes de REH / DAL / SEEN / SAD / TAH / AIN / FEH / QAF / KAF / GAF / LAM / NOON / HEH / WAW / YEH), e 26 novos mapeamentos de Presentation Forms-A foram adicionados (15 de classe D com 4 formas + 11 de classe R com 2 formas). Notavelmente, o 'h' padrão do urdu HEH DOACHASHMEE (U+06BE → FBAA-FBAD) e o yeh final de palavra do urdu YEH BARREE (U+06D2 → FBAE-FBAF) agora são mapeados corretamente aos slots Forms-A que foram mal usados pela correção temporária ALEF WASLA / NOON GHUNNA da v2.119.52. A cobertura estática de Forms-A agora abrange mais de 40 caracteres de origem.

 

YEH-HAMZA + vowel ligature post-pass (v2.119.58): uma pós-passada adicionada a _ApplyArabicShaping depois do shaping posicional cobre os 8 pares de ligaduras do bloco Forms-A U+FBEA-U+FBFB — YEH-HAMZA + ALEF / AE / WAW / U / OE / YU / E / ALEF MAKSURA. Cada par emite a forma isolated (FBEA / FBEC / FBEE / FBF0 / FBF2 / FBF4 / FBF6 / FBF9) mais a forma final base+1. Os slots de forma inicial / medial FBF8 / FBFB ficam para a engine GSUB via opt-in de sfArabicGSUB. Construído sobre o mesmo esqueleto do LAM-ALEF da v2.119.32.

 

Allah ligature (v2.119.60): a sequência de quatro caracteres ALEF + LAM + LAM + HEH funde-se em U+FDF2 ARABIC LIGATURE ALLAH ISOLATED FORM. Implementada como uma pós-passada estática no nível de codepoints depois do LAM-ALEF da v2.119.32 e do YEH-HAMZA da v2.119.58 na cadeia de _ApplyArabicShaping.

 

Bismillah phrase ligature (v2.119.62): a frase padrão Bismillah de 22 codepoints "بسم الله الرحمن الرحيم" funde-se em um único glifo U+FDFD ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM. Roda como a primeira pré-passada em _ApplyArabicShaping (antes do LAM-ALEF), de modo que o glifo Bismillah fundido chegue ao restante do pipeline como um único codepoint e não seja retocado por substituições a jusante.

 

Public Query Helpers

GetArabicJoiningClass retorna a classe de ligação Unicode usada pelo shaper árabe estático. GetArabicPosition resolve um caractere em um run para a posição isolated, initial, medial ou final, de modo que chamadores inspecionem ou espelhem as mesmas decisões de shaping antes de emitir texto

 

Como os chamadores o invocam

Ligue o pipeline uma única vez com PDF.AutoShapeArabic:= True; a partir daí ele roda automaticamente dentro dos métodos de emissão de texto Unicode — nenhuma chamada explícita de "shape isto" é exigida. Passe strings árabe / persa / urdu de entrada Unicode a THPDFPage.TextOut, THPDFPage.UnicodeTextOut ou THPDFPage.RtLTextOut e o HotPDF mapeará cada codepoint de entrada à presentation form dele antes de gravar o operador de exibição de texto do PDF. Free text annotations desenhadas com a fonte da página recebem o mesmo shaping. Os bytes Unicode originais também são capturados em FUnicodeUsedCps para geração do ToUnicode CMap, de modo que copy / paste no leitor e leitores de tela ainda vejam o payload Unicode original.

 

Requisitos de fontes

A fonte registrada via RegisterUnicodeTTF deve conter glifos tanto do bloco Arabic Presentation Forms-B (U+FE70 - U+FEFC) quanto (para persa / urdu) da faixa relevante de Arabic Presentation Forms-A (U+FB50 - U+FDFF). Fontes recomendadas que trazem o conjunto completo:

 

Noto Sans Arabic (Latin + Arabic; Forms-A + Forms-B + Arabic Extended-A).

Noto Naskh Arabic, Noto Naskh Arabic UI.

Amiri (Naskh tradicional, cobertura completa Forms-A + Forms-B).

Scheherazade New (SIL, desenhada para línguas do mundo muçulmano).

Microsoft Arabic Typesetting / Tahoma / Times New Roman (Windows-bundled, full Forms-B; some have Forms-A coverage).

 

Quando a fonte registrada não tem um glifo para uma presentation form derivada, o HotPDF recai no codepoint Unicode base e o emite inalterado; leitores consumidores podem então tentar o próprio shaping deles (Acrobat, Foxit) ou renderizar .notdef.

 

Fluxo de trabalho típico

 

PDF.RegisterUnicodeTTF('NotoArab', 'NotoSansArabic-Regular.ttf');

PDF.AutoShapeArabic:= True;

PDF.BeginDoc;

PDF.CurrentPage.SetFont('NotoArab', [], 14);

PDF.CurrentPage.RtLTextOut(100, 700, 0,

  UnicodeString(#$0645#$0631#$062D#$0628#$0627));  // "marhaba" (hello)

PDF.EndDoc;

 

Integração automática ao pipeline da Phase 8 (v2.119.59 - v2.119.68)

A v2.119.59 introduziu a propriedade opt-in ShapingFeatures: THPDFShapingFeatures e o enum THPDFShapingFeature, que eleva o pipeline de shaping além da fusão estática de pós-passada para substituição automática específica da fonte guiada por GSUB. Defina PDF.ShapingFeatures := [sfArabicGSUB] para aplicar as consultas nativas árabes init, medi, fina, isol, rlig, calt e rclt da fonte registrada e emitir os IDs de glifos contextuais resultantes; adicione sfCursiveAttachment para aplicar âncoras cursivas de entrada/saída GPOS a esse run com shaping; adicione sfStandardLigatures para Standard Ligatures latinas (FB00-FB06 ff / fi / fl / ffi / ffl / ſt / st via ApplyLatinLigatureRefinement da v2.119.65); adicione sfIndicShaping para habilitar a pré-passada de reordenação de devanágari (v2.119.67). O padrão [] preserva saída byte-idêntica para chamadores que dependem do pipeline estático.

 

Quando sfArabicGSUB está definido, o shaper estático de Unicode Presentation Forms é contornado em favor das próprias regras GSUB da fonte. O HotPDF emite IDs de glifos contextuais nativos por meio de codepoints sintéticos quando esses glifos não são alcançáveis pelo cmap da fonte, mantém o subset embutido fechado e grava mapeamentos reversos ToUnicode para copy e paste. Chamadores que quiserem que o shaper estático continue rodando para cobertura de codepoints fora do que o GSUB da fonte declara devem deixar sfArabicGSUB desligado e confiar na cadeia estática de pós-passadas

 

Mapeamento reverso de ligaduras do ToUnicode CMap (v2.119.61, v2.119.62, v2.119.65)

O CMap ToUnicode Adobe-Identity-UCS emitido por RegisterUnicodeTTF traz entradas bfchar de mapeamento reverso para todo codepoint de ligadura que a cadeia de pós-processamento pode produzir. A v2.119.61 adicionou 27 entradas (8 LAM-ALEF + 18 da família YEH-HAMZA + 1 Allah); a v2.119.62 adicionou o Bismillah (U+FDFD); a v2.119.65 adicionou 7 entradas de ligaduras padrão do Latin (FB00-FB06). Ao copiar e colar em um leitor, qualquer glifo de ligadura é resolvido de volta para a sequência de codepoints original, e o PDF gerado continua acessível.

 

Emissão de codepoints sintéticos na PUA (v2.119.68)

AssignSyntheticCodepointForGID(GID; out CP): Boolean + GetSyntheticCodepointForGID(GID): Word permitem que código do produtor emita GIDs substitutos de GSUB que não têm codepoint Unicode natural alcançável pelo cmap da fonte. O alocador distribui codepoints na Private Use Area (U+E000 - U+F8FF, 6400 slots) e espelha a atribuição em FUnicodeCpToGid (para que /CIDToGIDMap resolva o CP sintético de volta ao GID alvo no leitor consumidor), FAcroFormUnicodeAdvances (para que o word-wrap da v2.65 encontre a fração em correta) e uma tabela de consulta reversa por GID (para que requisições repetidas de atribuição sejam idempotentes). Use isto para formas de clusters de devanágari, alternates estilísticos e sequências de variação ideográfica CJK que o GSUB introduz mas o cmap não alcança.

 

Relação com a engine OpenType GSUB

O shaper estático de pós-passada descrito acima (v2.85.0 + v2.119.32 / 58 / 60 / 62) é independente do OpenType GSUB engine por padrão. Quando sfArabicGSUB é habilitado por meio de ShapingFeatures, a engine GSUB passa a fazer parte do caminho de emissão no lado do produtor: o HotPDF consulta o cmap para construir um array de GIDs base, aplica consultas GSUB posicionais e contextuais árabes nativas a esse run de glifos, atribui codepoints sintéticos para IDs de glifos substitutos que não têm Unicode Presentation Form e chama MarkUnicodeGlyphUsed para manter os glifos substitutos dentro do subset da fonte embutida.

 

Para glifos substitutos sem um codepoint Unicode, os chamadores combinam ShapingFeatures com o alocador de codepoints sintéticos PUA da v2.119.68, de modo que o GID substituto continue alcançável pelo pipeline hex padrão. A cadeia estática de pós-passadas permanece o fallback padrão para codepoints que as declarações GSUB da fonte não cobrem.

 

Escopo e limitações

O algoritmo BiDi permanece fora desta página: chamadores ainda precisam ordenar por conta própria runs mistos LTR e RTL ou usar uma biblioteca BiDi separada. O suporte a GPOS, índico/tibetano/mongol, hebraico, N'Ko, Adlam, tailandês/lao e javanês agora vive em páginas separadas de flags de shaping opt-in e de APIs, de modo que esta página foca apenas no shaping árabe estático e baseado em GSUB

 

See also: OpenType GSUB Substitution Engine, Pipeline automático de shaping (Fase 8), Shaping siríaco / mongol / devanágari, THotPDF.AssignSyntheticCodepointForGID, THPDFPage.RtLTextOut, THPDFPage.UnicodeTextOut, Subsetting de fontes CFF / OpenType