Logosulfite.app
rafagazani/sulfite 999999

PDF

Renderização em PDF com fontes, etiquetas e page settings

PDF#

O renderer padrão. Gera PDF multi-página com posicionamento absoluto, fontes customizáveis e suporte a etiquetas.

Uso#

final engine = SulfiteEngineImpl();
final report = await engine.parseReport(reportJson);
final context = await engine.processData(report, payload);

// Em memória
final pdfBytes = await engine.renderToPdf(context);

// Direto para arquivo
await engine.renderToPdfFile(context, 'output.pdf');

Como funciona#

O PDF renderer usa package:pdf com pw.MultiPage. Cada band vira um container com altura fixa e elementos posicionados via pw.Stack + pw.Positioned(left: x, top: y).

┌─ pw.MultiPage ───────────────────────────┐
│ ┌─ Header ─────────────────────────────┐ │  ← repete em toda página
│ │  pw.Stack [pw.Positioned(x,y)...]    │ │
│ └──────────────────────────────────────┘ │
│ ┌─ Detail (row 1) ────────────────────┐ │  ← uma por registro
│ │  pw.Stack [pw.Positioned(x,y)...]    │ │
│ └──────────────────────────────────────┘ │
│ ┌─ Detail (row 2) ────────────────────┐ │
│ │  ...                                 │ │
│ └──────────────────────────────────────┘ │
│ ┌─ Summary ───────────────────────────┐ │  ← uma vez
│ │  pw.Stack [pw.Positioned(x,y)...]    │ │
│ └──────────────────────────────────────┘ │
│ ┌─ Footer ─────────────────────────────┐ │  ← repete em toda página
│ │  pw.Stack [pw.Positioned(x,y)...]    │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────┘

Page Settings#

O formato da página é definido no pageSettings do relatório:

{
  "pageSettings": {
    "format": "A4",
    "orientation": "portrait",
    "margins": { "left": 40, "right": 40, "top": 40, "bottom": 40 }
  }
}

Orientação "landscape" inverte largura e altura automaticamente.

Paginação#

Header e Footer repetem automaticamente em cada página. Use {page} e {totalPages} em elementos Text e Field:

{ "type": "text", "id": "pg", "x": 250, "y": 10, "content": "Página {page} de {totalPages}" }

Quebra de página#

Qualquer band pode forçar uma nova página com forcePageBreakBefore:

{ "type": "summary", "id": "sum", "height": 60, "forcePageBreakBefore": true, "elements": [...] }

Fontes customizadas#

O FontLoader permite carregar fontes TTF para o PDF:

import 'package:sulfite_core/sulfite_core.dart';

// Flutter app — lê do asset bundle
final fonts = await FontLoader.load(
  loader: const AssetFontBytesLoader(),
  regular: 'assets/fonts/Inter-Regular.ttf',
  bold: 'assets/fonts/Inter-Bold.ttf',
  italic: 'assets/fonts/Inter-Italic.ttf',
  boldItalic: 'assets/fonts/Inter-BoldItalic.ttf',
);

// CLI / servidor — lê do sistema de arquivos
final fonts = await FontLoader.load(
  loader: const FileFontBytesLoader(),
  regular: '/usr/share/fonts/Inter-Regular.ttf',
  bold: '/usr/share/fonts/Inter-Bold.ttf',
);

Ver detalhes em Fontes customizadas.

Etiquetas#

O PDF renderer suporta modo etiqueta via labelConfig no pageSettings. Ver Etiquetas.

Todos os 14 elementos#

O renderer PDF suporta todos os 14 tipos de elementos: Text, Field, Aggregate, Image, Table, Chart, Barcode, Line, Rect, Circle, RichText e Spacer.

Bands com altura dinâmica#

Bands com height: 0 e um único TableElement como conteúdo têm altura calculada automaticamente pelo renderer PDF. O table expande para acomodar todas as linhas de dados sem cortar o conteúdo.

{
  "type": "detail",
  "id": "det_tabela",
  "height": 0,
  "dataSourceId": "items",
  "elements": [
    {
      "type": "table",
      "id": "tab",
      "x": 0, "y": 0,
      "width": 520,
      "dataSourceId": "items",
      "columns": [...]
    }
  ]
}

Quando height == 0 e a band não contém um TableElement, a band é omitida do PDF. Este modo só é suportado no PDF renderer; nos demais formatos (HTML, CSV, Excel) a height é obrigatória.

Gráficos no PDF#

Os gráficos são renderizados nativamente com package:pdf (sem dependências externas). Detalhes por tipo:

TipoComportamento
Bar (agrupado)Cada série usa offset para barras lado a lado
Bar (empilhado)Camadas cumulativas desenhadas em ordem reversa
LineLinhas com pontos conectados
PieFatias com cores da paleta padrão; valores ≤ 0 são omitidos

Legenda, cores, grade e borda seguem o ChartOptions do JSON. Ver Chart.