Skip to content

xFPDF: muda core_fonts_encoding para cp1252#165

Merged
antoniospneto merged 1 commit into
mainfrom
fix/cp1252-core-fonts-encoding
May 29, 2026
Merged

xFPDF: muda core_fonts_encoding para cp1252#165
antoniospneto merged 1 commit into
mainfrom
fix/cp1252-core-fonts-encoding

Conversation

@antoniospneto
Copy link
Copy Markdown
Contributor

Resumo

O fpdf2 usa core_fonts_encoding="latin-1" por padrão. Latin-1 (ISO-8859-1) não cobre vários caracteres tipográficos que aparecem em texto colado de Word/email — en-dash , em-dash , aspas curvas " " ' ', reticências , bullet , NBSP \xa0, € , ™ , etc. (a faixa 0x80–0x9F do Latin-1 é ocupada por caracteres de controle invisíveis).

Quando qualquer um desses chega num campo de texto livre (ex.: xDescServ, xNome, infCpl), o fpdf2 levanta FPDFUnicodeEncodingException e quebra a geração do PDF.

Esse PR muda o encoding para cp1252 (WinAnsiEncoding), que é superset estrito do Latin-1 e cobre todos esses caracteres.

Refs: #162

Por que cp1252

  • Superset estrito do latin-1 — nada que renderizava antes deixa de renderizar.
  • É o mesmo encoding usado pelo gerador oficial de DANFSE do SERPRO (confirmado via pdffonts em 10 DANFSE oficiais: todos com encoding=WinAnsi, fonte Segoe WP TrueType embarcada). Ou seja, esta mudança coloca a biblioteca em paridade de cobertura de caracteres com o gerador oficial.
  • Portável — codec da stdlib do Python (tabela em memória, igual em Linux/macOS/Windows). WinAnsiEncoding está na spec PDF (ISO 32000), todo leitor tem hard-coded. Não introduz dependência de fonte ou de SO.
  • Sem custo — não embarca fonte, não muda tamanho do PDF.

Escopo

A mudança fica no xFPDF (base compartilhada) e beneficia todos os tipos de documento que herdam dele: DANFE, DANFSE, DACTE, DAMDFE, DACCE.

Diff

class xFPDF(FPDF):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.core_fonts_encoding = "cp1252"

Testes

  • Adicionado tests/test_xfpdf.py com regression guard parametrizado cobrindo 11 caracteres tipográficos que antes disparavam a exceção.
  • Validação por controle negativo: sem o fix, 10 dos 11 testes falham (o único que passa é o NBSP \xa0, que coincide com Latin-1 — comportamento esperado).
  • Suite completa: 70/70 passando (58 anteriores + 12 novos).

Test plan

  • Testes novos passam (pytest tests/test_xfpdf.py)
  • Suite completa passa (pytest tests/ --ignore=tests/test_cli.py)
  • Controle negativo: testes falham sem o fix (confirma que pegam a regressão)
  • Erro original do DANFSE: Erro do Caractere "–" #162 reproduzido com FPDF puro (confirma que o fix corrige a causa-raiz)
  • pdftotext recupera os caracteres literais do PDF gerado (não viram ?)

O fpdf2 usa core_fonts_encoding="latin-1" por padrão, que não cobre
caracteres tipográficos comuns vindos de autocorreção do Word/email
(en-dash, em-dash, aspas curvas, reticências, bullet, NBSP, etc.).
Quando qualquer um deles aparece em xDescServ, xNome, infCpl ou outros
campos de texto livre, o fpdf2 levanta FPDFUnicodeEncodingException e
a geração do PDF quebra.

cp1252 (WinAnsiEncoding) é um superset estrito do latin-1 que cobre
todos esses caracteres. É também o mesmo encoding usado pelo gerador
oficial de DANFSE do SERPRO (verificado via pdffonts em PDFs emitidos
pelo governo: encoding=WinAnsi), então essa mudança coloca o
BrazilFiscalReport em paridade de cobertura de caracteres com o
gerador oficial.

A mudança fica no xFPDF e beneficia todos os tipos de documento que
herdam dele: DANFE, DANFSE, DACTE, DAMDFE, DACCE.

Adiciona tests/test_xfpdf.py com um regression guard parametrizado
cobrindo os caracteres tipográficos que antes disparavam a exceção.

Refs: #162
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.65%. Comparing base (786129f) to head (4208489).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #165   +/-   ##
=======================================
  Coverage   95.65%   95.65%           
=======================================
  Files          32       32           
  Lines        4393     4396    +3     
  Branches      311      311           
=======================================
+ Hits         4202     4205    +3     
  Misses        125      125           
  Partials       66       66           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@antoniospneto antoniospneto merged commit dd8baf4 into main May 29, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant