Skip to content

Layout de página/coluna programático e configurável por periódico (modelo intermediário: decisão + largura + justificativa) #1278

Description

@Rossi-Luciano

Descrição da tarefa

Hoje o gerador de PDF decide layout (1 ou 2 colunas, largura de tabela/figura) através de duas heurísticas isoladas e desconectadas:

  • renderer/docx/figure.py::decide_figure_layout decide por DPI da imagem.
  • pipeline/xml.py::determine_table_layout decide por contagem de coluna (> 4).

Nenhuma das duas retorna largura real nem justificativa — só um rótulo de string. A geometria de página (enum.py::PAGE_ATTRIBUTES) é uma constante fixa em A4/2-colunas, sem possibilidade de configuração por periódico. Isso já causou pelo menos um caso real de infidelidade visual confirmado contra PDF publicado (ver "Considerações").

Esta tarefa introduz um "modelo intermediário" de layout — LayoutConfig — como abstração central e reutilizável que:

  • Centraliza geometria de página/coluna/margem por periódico (PageProfile), com fallback para o default atual (A4, 2 colunas) quando o periódico não estiver calibrado.
  • Faz tabela e figura consultarem o mesmo contexto de layout, em vez de cada uma ter sua própria noção de largura disponível.
  • Retorna toda decisão como objeto estruturado (LayoutDecision): largura resolvida + justificativa legível + origem do julgamento (medido/heurística/override) — não só um rótulo.
  • Expõe uma abstração explícita (full_width()) para "quebrar pra largura total e restaurar depois", substituindo a lógica de quebra/restauração de seção hoje duplicada entre tabela e figura.
  • Permite calibrar um periódico por ISSN eletrônico (profiles/{issn_epub}.json), detectado automaticamente a partir do XML de entrada — sem precisar de flag manual.

Subtarefas

  • PageProfile/LayoutDecision/WidthClass/LayoutConfig (packtools/sps/formats/pdf/layout_config.py)
  • determine_table_layout consulta LayoutConfig quando fornecido, mantendo o comportamento atual quando não
  • decide_figure_layout/add_figure/_compute_single_column_width (figure.py) idem
  • _compute_table_width (table.py) idem
  • pipeline_docx detecta o ISSN eletrônico do XML e carrega o perfil calibrado automaticamente (load_profile), com fallback ao default quando não calibrado
  • Registro de perfis por periódico em packtools/sps/formats/pdf/profiles/{issn_epub}.json (3 periódicos calibrados por medição contra PDF publicado: Acta Amazonica, Acta Botanica Brasilica, Anuário Antropológico)
  • Testes automatizados cobrindo 1 coluna, 2 colunas e alternância temporária com retorno correto (tests/sps/formats/pdf/test_layout_config.py, mais testes de integração em pipeline/test_xml.py e novo renderer/docx/test_figure.py/test_table.py)
  • Validação ponta a ponta contra PDF publicado real, para os 3 periódicos calibrados (comparação visual + medição de bounding box)
  • Expor seleção manual de 1/2 colunas via API Python e CLI (pdf_generator) — hoje a escolha é sempre automática via perfil, sem override explícito do usuário final
  • Ligar largura real de coluna medida (column_min_widths_pt) na decisão de tabela — hoje determine_table_layout sempre cai no fallback heurístico (contagem de coluna), porque não há largura por coluna medida disponível nesse ponto do pipeline
  • Calibrar mais periódicos além dos 3 iniciais

Considerações e notas

  • Achado motivador: teste ponta a ponta com tests/fixtures/pdf/a1.xml (Acta Amazonica) contra o PDF publicado real mostrou página em altura errada (A4 hardcoded vs. altura real do periódico) e um bug real e independente em _compute_single_column_width/_compute_table_width: ambos assumiam sempre 2 colunas (/2 fixo), o que só quebra visivelmente num periódico calibrado para 1 coluna (Anuário Antropológico) — corrigido nesta tarefa.
  • Dimensionamento de largura de figura dentro do teto disponível (quando não precisa de largura total) não tem regra geral confirmada — uma hipótese de DPI de metadado não confiável (96/72 como artefato) bateu para um periódico e foi contrariada por outro (Acta Botanica Brasilica, onde o alvo real usa ~2.2x o tamanho nativo confiável). Documentado como limitação conhecida em profiles/1677-941X.json, não resolvido nesta tarefa — indicação de que precisa calibração por figura, não por periódico.
  • Vale coordenar com a refatoração em andamento (Refatoração: separação entre modelos de dados e modelos de validação #1146, separação entre modelos de dados e validação) antes de expandir LayoutConfig além do escopo desta tarefa, para não duplicar modelagem de fig/tablewrap.
  • Relacionado: pdf_generator  #773 (bug no pdf_generator CLI, reproduzido durante os testes desta tarefa, não corrigido aqui — fora de escopo).

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions