Phase 5 Implementation: - Link annotations in PDF (clickable in viewers) - Page.addUrlLink() - add URL annotation - Page.addInternalLink() - add internal page link - Page.urlLink() / writeUrlLink() - visual + annotation combined - Page.getLinks() - retrieve page links - OutputProducer generates /Annots arrays for pages - Link annotation objects with /Type /Annot /Subtype /Link New example: - links_demo.zig - demonstrates URL and internal links - 2 pages with cross-page navigation - External URLs (example.com, GitHub, mailto) - Internal links between pages Final state: - 7 examples working (hello, invoice, text_demo, image_demo, table_demo, pagination_demo, links_demo) - ~70 tests passing - Complete feature set for document generation zpdf is now feature-complete for typical document generation needs: text, tables, images, pagination, and clickable links. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
300 lines
7.3 KiB
Markdown
300 lines
7.3 KiB
Markdown
# zpdf - Generador PDF para Zig
|
|
|
|
> **Ultima actualizacion**: 2025-12-08
|
|
> **Lenguaje**: Zig 0.15.2
|
|
> **Estado**: v0.5 - Clickable Links + Complete Feature Set
|
|
> **Fuente principal**: fpdf2 (Python) - https://github.com/py-pdf/fpdf2
|
|
|
|
## Descripcion del Proyecto
|
|
|
|
**zpdf** es una libreria pura Zig para generacion de documentos PDF. Sin dependencias externas, compila a un binario unico.
|
|
|
|
**Filosofia**:
|
|
- Zero dependencias (100% Zig puro)
|
|
- API simple y directa inspirada en fpdf2
|
|
- Enfocado en generacion de facturas/documentos comerciales
|
|
- Soporte completo: texto, tablas, imagenes, links, paginacion
|
|
|
|
**Caracteristicas principales**:
|
|
- Sistema de texto completo (cell, multiCell, alineacion, word wrap)
|
|
- 14 fuentes Type1 standard (Helvetica, Times, Courier, etc.)
|
|
- Imagenes JPEG embebidas (passthrough, sin re-encoding)
|
|
- Table helper para tablas formateadas
|
|
- Paginacion automatica (numeros de pagina, headers, footers)
|
|
- Links clickeables (URLs externas + links internos entre paginas)
|
|
- Colores RGB, CMYK, Grayscale
|
|
|
|
---
|
|
|
|
## Estado Actual - v0.5
|
|
|
|
### Funcionalidades Implementadas
|
|
|
|
| Categoria | Funcionalidad | Estado |
|
|
|-----------|---------------|--------|
|
|
| **Documento** | | |
|
|
| | Crear PDF 1.4 | OK |
|
|
| | Metadatos (titulo, autor, etc.) | OK |
|
|
| | Multiples paginas | OK |
|
|
| | Tamanos estandar (A4, Letter, A3, A5, Legal) | OK |
|
|
| **Texto** | | |
|
|
| | drawText() - texto en posicion | OK |
|
|
| | cell() - celda con bordes/relleno | OK |
|
|
| | multiCell() - word wrap automatico | OK |
|
|
| | Alineacion (left, center, right) | OK |
|
|
| | 14 fuentes Type1 standard | OK |
|
|
| **Graficos** | | |
|
|
| | Lineas | OK |
|
|
| | Rectangulos (stroke, fill) | OK |
|
|
| | Colores RGB/CMYK/Gray | OK |
|
|
| **Imagenes** | | |
|
|
| | JPEG embedding | OK |
|
|
| | image() / imageFit() | OK |
|
|
| | Aspect ratio preservation | OK |
|
|
| **Tablas** | | |
|
|
| | Table helper | OK |
|
|
| | header(), row(), footer() | OK |
|
|
| | Alineacion por columna | OK |
|
|
| | Estilos personalizados | OK |
|
|
| **Paginacion** | | |
|
|
| | Numeros de pagina | OK |
|
|
| | Headers automaticos | OK |
|
|
| | Footers automaticos | OK |
|
|
| | skip_pages option | OK |
|
|
| **Links** | | |
|
|
| | URL links clickeables | OK |
|
|
| | Internal page links | OK |
|
|
| | Visual styling (azul+subrayado) | OK |
|
|
| | Link annotations | OK |
|
|
|
|
### Tests y Ejemplos
|
|
|
|
- **~70 tests** unitarios pasando
|
|
- **7 ejemplos** funcionales:
|
|
- `hello.zig` - PDF minimo
|
|
- `invoice.zig` - Factura completa
|
|
- `text_demo.zig` - Sistema de texto
|
|
- `image_demo.zig` - Imagenes JPEG
|
|
- `table_demo.zig` - Table helper
|
|
- `pagination_demo.zig` - Paginacion multi-pagina
|
|
- `links_demo.zig` - Links clickeables
|
|
|
|
---
|
|
|
|
## Arquitectura
|
|
|
|
```
|
|
zpdf/
|
|
├── CLAUDE.md # Documentacion del proyecto
|
|
├── build.zig # Sistema de build
|
|
├── src/
|
|
│ ├── root.zig # Exports publicos
|
|
│ ├── pdf.zig # Pdf facade (API principal)
|
|
│ ├── page.zig # Page + texto + links
|
|
│ ├── content_stream.zig # Operadores PDF
|
|
│ ├── table.zig # Table helper
|
|
│ ├── pagination.zig # Paginacion, headers, footers
|
|
│ ├── links.zig # Link types
|
|
│ ├── fonts/
|
|
│ │ └── type1.zig # 14 fuentes Type1 + metricas
|
|
│ ├── graphics/
|
|
│ │ └── color.zig # Color (RGB, CMYK, Gray)
|
|
│ ├── images/
|
|
│ │ ├── jpeg.zig # JPEG parser
|
|
│ │ ├── png.zig # PNG metadata
|
|
│ │ └── image_info.zig # ImageInfo struct
|
|
│ ├── objects/
|
|
│ │ └── base.zig # PageSize, Orientation
|
|
│ └── output/
|
|
│ └── producer.zig # Serializa PDF + images + links
|
|
└── examples/
|
|
├── hello.zig
|
|
├── invoice.zig
|
|
├── text_demo.zig
|
|
├── image_demo.zig
|
|
├── table_demo.zig
|
|
├── pagination_demo.zig
|
|
└── links_demo.zig
|
|
```
|
|
|
|
---
|
|
|
|
## API Quick Reference
|
|
|
|
### Documento Basico
|
|
|
|
```zig
|
|
const zpdf = @import("zpdf");
|
|
|
|
var doc = zpdf.Pdf.init(allocator, .{});
|
|
defer doc.deinit();
|
|
|
|
doc.setTitle("Mi Documento");
|
|
var page = try doc.addPage(.{});
|
|
|
|
try page.setFont(.helvetica_bold, 24);
|
|
try page.drawText(50, 750, "Hello, PDF!");
|
|
|
|
try doc.save("output.pdf");
|
|
```
|
|
|
|
### Celdas y Tablas
|
|
|
|
```zig
|
|
// cell() simple
|
|
try page.cell(100, 20, "Hello", zpdf.Border.all, .center, true);
|
|
|
|
// multiCell con word wrap
|
|
try page.multiCell(400, null, texto_largo, zpdf.Border.none, .left, false);
|
|
|
|
// Table helper
|
|
const widths = [_]f32{ 200, 100, 100 };
|
|
var table = zpdf.Table.init(page, .{
|
|
.col_widths = &widths,
|
|
});
|
|
try table.header(&.{ "Producto", "Qty", "Precio" });
|
|
try table.row(&.{ "Item A", "10", "$50" });
|
|
try table.footer(&.{ "Total", "", "$50" });
|
|
```
|
|
|
|
### Imagenes
|
|
|
|
```zig
|
|
const img_idx = try doc.addJpegImageFromFile("foto.jpg");
|
|
const info = doc.getImage(img_idx).?;
|
|
try page.image(img_idx, info, 50, 500, 200, 150);
|
|
```
|
|
|
|
### Links Clickeables
|
|
|
|
```zig
|
|
// URL link con visual styling
|
|
_ = try page.urlLink(100, 700, "Click aqui", "https://example.com");
|
|
|
|
// O desde posicion actual
|
|
_ = try page.writeUrlLink("Visitar web", "https://example.com");
|
|
|
|
// Link interno (saltar a pagina)
|
|
try page.addInternalLink(2, 100, 700, 150, 20); // page 2
|
|
```
|
|
|
|
### Paginacion
|
|
|
|
```zig
|
|
// Numeros de pagina
|
|
try zpdf.Pagination.addPageNumbers(&doc, .{
|
|
.format = "Page {PAGE} of {PAGES}",
|
|
.position = .bottom_center,
|
|
});
|
|
|
|
// Header con linea
|
|
try zpdf.addHeader(&doc, "Documento", .{
|
|
.draw_line = true,
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Comandos
|
|
|
|
```bash
|
|
# Zig path
|
|
ZIG=/mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig
|
|
|
|
# Compilar
|
|
$ZIG build
|
|
|
|
# Tests
|
|
$ZIG build test
|
|
|
|
# Ejemplos
|
|
./zig-out/bin/hello
|
|
./zig-out/bin/invoice
|
|
./zig-out/bin/text_demo
|
|
./zig-out/bin/image_demo
|
|
./zig-out/bin/table_demo
|
|
./zig-out/bin/pagination_demo
|
|
./zig-out/bin/links_demo
|
|
```
|
|
|
|
---
|
|
|
|
## Roadmap Completado
|
|
|
|
### Fase 1 - Core (COMPLETADO)
|
|
- [x] Estructura PDF 1.4
|
|
- [x] Paginas multiples
|
|
- [x] Texto basico
|
|
- [x] Graficos (lineas, rectangulos)
|
|
- [x] Colores
|
|
|
|
### Fase 2 - Texto Avanzado (COMPLETADO)
|
|
- [x] cell() / cellAdvanced()
|
|
- [x] multiCell() con word wrap
|
|
- [x] Alineacion
|
|
- [x] Bordes
|
|
|
|
### Fase 3 - Imagenes (COMPLETADO)
|
|
- [x] JPEG embedding
|
|
- [x] image() / imageFit()
|
|
- [x] PNG metadata (embedding pendiente)
|
|
|
|
### Fase 4 - Utilidades (COMPLETADO)
|
|
- [x] Table helper
|
|
- [x] Paginacion
|
|
- [x] Headers/Footers
|
|
- [x] Links visuales
|
|
|
|
### Fase 5 - Links Clickeables (COMPLETADO)
|
|
- [x] URL annotations
|
|
- [x] Internal page links
|
|
- [x] Link annotations en PDF
|
|
|
|
### Futuro (Opcional)
|
|
- [ ] PNG embedding completo
|
|
- [ ] Compresion de streams
|
|
- [ ] Fuentes TTF
|
|
- [ ] Bookmarks
|
|
|
|
---
|
|
|
|
## Historial
|
|
|
|
### 2025-12-08 - v0.5 (Links Clickeables)
|
|
- Link annotations clickeables en PDF
|
|
- addUrlLink() / addInternalLink() en Page
|
|
- urlLink() / writeUrlLink() combinan visual + annotation
|
|
- OutputProducer genera /Annots en pages
|
|
- links_demo.zig ejemplo con 2 paginas
|
|
- 7 ejemplos, ~70 tests
|
|
|
|
### 2025-12-08 - v0.4 (Utilidades)
|
|
- Table helper
|
|
- Pagination (numeros de pagina)
|
|
- Headers/Footers automaticos
|
|
- Links visuales
|
|
|
|
### 2025-12-08 - v0.3 (Imagenes)
|
|
- JPEG embedding
|
|
- image() / imageFit()
|
|
|
|
### 2025-12-08 - v0.2 (Texto)
|
|
- cell() / multiCell()
|
|
- Word wrap, alineacion
|
|
|
|
### 2025-12-08 - v0.1 (Core)
|
|
- Estructura inicial
|
|
|
|
---
|
|
|
|
## Equipo
|
|
|
|
```
|
|
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/
|
|
git remote: git@git.reugenio.com:reugenio/zpdf.git
|
|
```
|
|
|
|
---
|
|
|
|
**zpdf - Generador PDF para Zig**
|
|
*v0.5 - Feature Complete - 2025-12-08*
|