Repository navigation
fix(danfse): incorporar Liberation Sans como tipografia livre padrão #137
Description
Objetivo
Garantir que o DANFSe gerado por `nfse-php` utilize, por padrão e sem configuração do consumidor, Liberation Sans Regular e Bold efetivamente incorporadas ao PDF, com distribuição legalmente adequada e comportamento previsível em servidores Linux.
A adoção de Liberation Sans é uma decisão arquitetural de substituição livre. Não representa atendimento literal aos nomes Arial e Microsoft Sans Serif exigidos na NT008 v1.02, item 2.4.
Comportamento atual
`DanfseGenerator` configura Helvetica como fonte padrão do Dompdf. `HTMLTemplate.php` contém nomes de famílias alternativas no CSS, mas a biblioteca não distribui os arquivos Liberation Sans nem comprova sua seleção efetiva no PDF padrão.
`DanfseFonts` já permite fontes TrueType locais externas, com validação de caminhos, registro CSS e isolamento de famílias/cache. Esse comportamento e a API pública devem ser preservados.
A suíte visual já gera documentos sintéticos, incluindo um teste de fontes externas com DejaVu Sans. O teste não comprova que a configuração padrão utiliza fontes livres incorporadas.
Implementação
- Incorporar os arquivos necessários de Liberation Sans 2.x Regular e Bold, obtidos de distribuição oficial identificável, verificando versão, integridade, autoria, SIL OFL 1.1, nomes reservados e direitos de redistribuição/incorporação.
- Incluir licença e atribuições pertinentes no pacote e no inventário REUSE, sem reclassificar as fontes como AGPL.
- Garantir que os arquivos estejam disponíveis tanto no checkout quanto nas distribuições Composer, sem downloads em tempo de execução.
- Registrar uma tipografia padrão interna no Dompdf, cobrindo rótulos, valores, cabeçalhos, campos destacados e marcas de estado. Não depender de correspondências de fontes instaladas no sistema operacional.
- Impedir fallback silencioso para Helvetica, Times ou outras famílias inesperadas. A falta de recursos obrigatórios deve produzir erro diagnóstico apropriado.
- Preservar o suporte a `DanfseConfig(fonts: new DanfseFonts(...))`, incluindo arquivos locais externos e isolamento de cache.
- Preservar a proteção contra colisões do cache estático de `FontMetrics` entre renderizações consecutivas, sem impor configuração administrativa adicional ao consumidor.
- Manter o contrato de página única A4 retrato, com conteúdo fiscal obrigatório preservado e abreviações de texto livre somente onde já permitidas.
- Atualizar apenas o contrato estável em `docs/danfse-v2-rendering.md`, distinguindo compatibilidade funcional/visual de conformidade nominal à NT008.
A abordagem interna de registro e cache deve ser escolhida após testar o comportamento real das versões Dompdf suportadas (`^2.0 || ^3.0`). Evitar novas dependências ou APIs públicas quando desnecessárias.
Critérios de aceitação
- A geração padrão funciona em ambiente limpo, sem fontes proprietárias e sem configuração externa.
- `pdffonts` identifica as fontes Liberation Sans efetivas, incluindo Regular e Bold quando utilizadas, com `emb=yes` e sem substituições inesperadas.
- Um arquivo de fonte ausente, ilegível ou inválido não resulta silenciosamente em PDF com outra família.
- Caracteres portugueses, acentuação, símbolos monetários e caracteres especiais esperados são renderizados corretamente.
- O HTML e o PDF preservam os rótulos, conteúdos, tamanhos mínimos e pesos exigidos para a apresentação, exceto pela divergência nominal das famílias.
- Casos sintéticos de nomes, municípios, endereços, descrições e informações complementares extensas mantêm legibilidade e uma única página A4.
- Ausência, zero real e valores informados permanecem distintos nos campos fiscais.
- Continuam corretos os cenários de ISSQN, retenções, IBS/CBS, regime especial ausente/0/outros códigos, produção restrita, cancelamento e substituição.
- Renderizações padrão → personalizada → padrão e personalizada A → personalizada B, no mesmo processo PHP, não contaminam a seleção de fontes nem o cache.
- Testes de empacotamento comprovam que binários, licença e atribuições acompanham a instalação Composer.
- A inspeção visual de PDFs sintéticos compara os casos relevantes com a referência anterior, incluindo canhoto, margens, bordas, contraste e quebras de linha.
- A documentação declara expressamente a divergência tipográfica nominal da NT008, sem alegar aprovação oficial da substituição.
- A API pública de `DanfseConfig`, `DanfseFonts` e `DanfseGenerator` permanece compatível, ou eventual mudança necessária possui justificativa e testes de migração.
Verificação
Reaproveitar e ampliar:
- `tests/Unit/Danfse/DanfseGeneratorTest.php`
- `tests/Unit/Danfse/DanfseGoldenReferenceTest.php`
- `tools/bin/render-danfse-visual-fixtures.php`
- `.github/workflows/danfse-visual.yml`
Executar `composer test`, `composer cs:check`, `composer psalm`, REUSE e os checks pertinentes. Usar `pdfinfo`, `pdffonts`, extração de texto e inspeção visual. Conservar evidências sintéticas nos artefatos da CI/PR, sem exigir igualdade byte a byte dos PDFs.
Não reduzir assertions nem remover cenários anteriores para obter CI verde.
Fora de escopo
- Redistribuir ou baixar automaticamente fontes Microsoft.
- Criar telas de configuração, upload ou download de fontes.
- Alterar XML fiscal, DPS, tributos, emissão, assinatura digital ou documentos históricos.
- Implementar regras fiscais pertencentes ao emissor.
- Produzir documentação versionada de andamento ou auditoria transitória.
Referências
- Épico: epic(danfse): concluir apresentação NT008 v1.02 com divergência tipográfica documentada #118.
- Auditoria concluída: audit(danfse): mapear conformidade de todos os blocos à NT 008 #119.
- Testes de referência concluídos: Validate DANFSe v2 rendering against official NT 008 reference cases #57.
- NT008 v1.02: https://www.gov.br/nfse/pt-br/biblioteca/documentacao-tecnica/rtc/nt-008-se-cgnfse-danfse-20260714-v1-02.pdf
- Liberation Fonts: https://github.com/liberationfonts/liberation-fonts
Activity
build(danfse): vendor verified Liberation Sans 2.1.5 font binaries (#137
fix(danfse): select validated bundled Liberation Sans by default (#137)
test(danfse): verify bundled font presence and renderer isolation (#137)
docs(danfse): clarify independently verified font provenance (#137)
test(danfse): extract visual PDF evidence checks into reusable PHP ve…
ci(danfse): run reusable and unit-tested PDF evidence verifier (#137)
fix(danfse): embed custom highlighted text without Helvetica fallback (…
ci(danfse): prove PDF rendering with Dompdf 2 and 3 (#137)
test(danfse): verify font binaries and OFL license inside Composer ar…
test(danfse): fix Composer archive root lookup and isolate legacy adv…
test(danfse): exercise all DANFSe cases on Dompdf 2/3 and document fo…
build(danfse): require Dompdf 3.1.6 and drop legacy 2.x compatibility (…
Merge pull request #138 from LibreCodeCoop/fix/danfse-liberation-sans…
vitormattos commentedon Oct 13, 2026
Aceite técnico da #137 — PR #138 integrado
Auditei a
mainno commit22b71d6b1a0949197412b625759d8015d32c1b54, com a mesma árvore de código do último SHA aprovado do PR #138 (f344818c826c28773400cf75e88511ee4ac78770).Critérios comprovados:
pdffontsconfirmaemb=yesnos dez PDFs sintéticos analisados.pdfinfo10/10), acentuação e símbolos monetários extraídos corretamente, rótulos e conteúdo fiscal preservados, inclusive nos cenários de regime especial ausente/0/9, imunidade, benefício zero e ISS não incidente.composer archive; ausência/adulteração das fontes gera erro em vez de fallback silencioso.dompdf/dompdf: ^3.1.6confirmada, sem retorno à série 2.x.Testes e CI: workflow visual aprovado com 145 testes / 532 assertions e artefato de dez PDFs; PHP 8.2, 8.3 e 8.4 com 464 testes / 1.784 assertions por versão. Os checks aplicáveis do SHA final registram 15 sucessos, um job automático ignorado, zero falhas; Psalm, estilo, dependências mínimas e REUSE aprovados. Referência visual anterior: run 38277928235.
Limites registrados, sem exagerar o aceite:
Conclusão: não há defeito reproduzível ou alteração adicional necessária no escopo da #137. Aceite técnico fundamentado e encerramento como concluída, preservadas as ressalvas acima. A atualização do pin do consumidor
akaunting-nfse, se necessária, é integração separada, não consequência automática deste merge.