zcatpdf/CLAUDE.md
reugenio 2996289953 feat: v0.2 - Complete text system (cell, multiCell, alignment)
Phase 1 - Refactoring:
- Modular architecture: fonts/, graphics/, objects/, output/
- Fixed Zig 0.15 API changes (ArrayListUnmanaged)
- Fixed memory issues in render()

Phase 2 - Text System:
- cell() with borders, fill, alignment
- cellAdvanced() with position control
- multiCell() with automatic word wrap
- ln() for line breaks
- getStringWidth() for text width calculation
- Page margins (setMargins, setCellMargin)
- Align enum (left, center, right)
- Border packed struct

New features:
- New Pdf API (cleaner than legacy Document)
- Document metadata (setTitle, setAuthor, setSubject)
- Color: RGB, CMYK, Grayscale support
- 52 unit tests passing
- New example: text_demo.zig

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 19:46:30 +01:00

416 lines
12 KiB
Markdown

# zpdf - Generador PDF para Zig
> **Ultima actualizacion**: 2025-12-08
> **Lenguaje**: Zig 0.15.2
> **Estado**: v0.2 - Sistema de texto completo (cell, multiCell, alignment)
> **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 para texto, tablas, imagenes y formas basicas
- Calidad open source (doc comments, codigo claro)
**Objetivo**: Ser el pilar para generar PDFs en Zig con codigo 100% propio, replicando funcionalidad de librerias maduras como fpdf2/gofpdf.
---
## Estado Actual del Proyecto
### Implementacion v0.2 (Sistema de Texto Completo)
| Componente | Estado | Archivo |
|------------|--------|---------|
| **Pdf (API Nueva)** | | |
| Pdf init/deinit | OK | `src/pdf.zig` |
| setTitle, setAuthor, setSubject | OK | `src/pdf.zig` |
| addPage (with options) | OK | `src/pdf.zig` |
| output() / render() | OK | `src/pdf.zig` |
| save() | OK | `src/pdf.zig` |
| **Document (Legacy)** | | |
| Document init/deinit | OK | `src/root.zig` |
| addPage (standard sizes) | OK | `src/root.zig` |
| render() / saveToFile() | OK | `src/root.zig` |
| **Page** | | |
| Page init/deinit | OK | `src/page.zig` |
| setFont / getFont / getFontSize | OK | `src/page.zig` |
| setFillColor / setStrokeColor / setTextColor | OK | `src/page.zig` |
| setLineWidth | OK | `src/page.zig` |
| setXY / setX / setY / getX / getY | OK | `src/page.zig` |
| setMargins / setCellMargin | OK | `src/page.zig` |
| drawText | OK | `src/page.zig` |
| writeText | OK | `src/page.zig` |
| **cell()** | OK | `src/page.zig` |
| **cellAdvanced()** | OK | `src/page.zig` |
| **multiCell()** | OK | `src/page.zig` |
| **ln()** | OK | `src/page.zig` |
| **getStringWidth()** | OK | `src/page.zig` |
| **getEffectiveWidth()** | OK | `src/page.zig` |
| drawLine | OK | `src/page.zig` |
| drawRect / fillRect / drawFilledRect | OK | `src/page.zig` |
| rect (with RenderStyle) | OK | `src/page.zig` |
| **Types** | | |
| PageSize enum (A4, Letter, A3, A5, Legal) | OK | `src/objects/base.zig` |
| Orientation enum (portrait, landscape) | OK | `src/objects/base.zig` |
| Font enum (14 Type1 fonts) | OK | `src/fonts/type1.zig` |
| Color struct (RGB, CMYK, Grayscale) | OK | `src/graphics/color.zig` |
| **Align enum (left, center, right)** | OK | `src/page.zig` |
| **Border packed struct** | OK | `src/page.zig` |
| **CellPosition enum** | OK | `src/page.zig` |
| ContentStream | OK | `src/content_stream.zig` |
| OutputProducer | OK | `src/output/producer.zig` |
### Tests
| Categoria | Tests | Estado |
|-----------|-------|--------|
| root.zig (integration) | 8 | OK |
| page.zig (Page operations) | 18 | OK |
| content_stream.zig | 6 | OK |
| graphics/color.zig | 5 | OK |
| fonts/type1.zig | 5 | OK |
| objects/base.zig | 5 | OK |
| output/producer.zig | 5 | OK |
| **Total** | **52** | OK |
### Ejemplos
| Ejemplo | Descripcion | Estado |
|---------|-------------|--------|
| hello.zig | PDF minimo con texto y formas | OK |
| invoice.zig | Factura completa realista | OK |
| **text_demo.zig** | Demo sistema de texto (cells, tables, multiCell) | OK |
---
## Arquitectura Modular
```
zpdf/
├── CLAUDE.md # Este archivo - estado del proyecto
├── build.zig # Sistema de build
├── src/
│ ├── root.zig # Exports publicos + Document legacy
│ ├── pdf.zig # Pdf facade (API nueva)
│ ├── page.zig # Page + sistema de texto
│ ├── content_stream.zig # Content stream (operadores PDF)
│ ├── fonts/
│ │ ├── mod.zig # Exports de fonts
│ │ └── type1.zig # 14 fuentes Type1 + metricas
│ ├── graphics/
│ │ ├── mod.zig # Exports de graphics
│ │ └── color.zig # Color (RGB, CMYK, Gray)
│ ├── objects/
│ │ ├── mod.zig # Exports de objects
│ │ └── base.zig # PageSize, Orientation, Unit
│ └── output/
│ ├── mod.zig # Exports de output
│ └── producer.zig # OutputProducer (serializa PDF)
├── examples/
│ ├── hello.zig # Ejemplo basico
│ ├── invoice.zig # Factura ejemplo
│ └── text_demo.zig # Demo sistema de texto
└── docs/
├── PLAN_MAESTRO_ZPDF.md
├── ARQUITECTURA_FPDF2.md
└── ARQUITECTURA_ZPDF.md
```
---
## Roadmap
### Fase 1 - Core + Refactoring (COMPLETADO)
- [x] Estructura documento PDF 1.4
- [x] Paginas (A4, Letter, A3, A5, Legal, custom)
- [x] Texto basico (14 fuentes Type1 built-in)
- [x] Lineas y rectangulos
- [x] Colores RGB, CMYK, Grayscale
- [x] Serializacion correcta
- [x] Refactoring modular (separar en archivos)
- [x] Arreglar errores Zig 0.15 (ArrayListUnmanaged)
### Fase 2 - Sistema de Texto (COMPLETADO)
- [x] cell() - celda con bordes, relleno, alineacion
- [x] cellAdvanced() - cell con control de posicion
- [x] multiCell() - texto con word wrap automatico
- [x] ln() - salto de linea
- [x] getStringWidth() - ancho de texto
- [x] Alineacion (left, center, right)
- [x] Bordes configurables (Border packed struct)
- [x] Margenes de pagina
- [x] 18 tests para sistema de texto
### Fase 3 - Imagenes (PENDIENTE)
- [ ] JPEG embebido
- [ ] PNG embebido (con alpha)
- [ ] Escalado y posicionamiento
- [ ] Aspect ratio preservation
### Fase 4 - Utilidades (PENDIENTE)
- [ ] Helper para tablas
- [ ] Numeracion de paginas
- [ ] Headers/footers automaticos
- [ ] Links/URLs
### Fase 5 - Avanzado (FUTURO)
- [ ] Fuentes TTF embebidas
- [ ] Compresion de streams (zlib)
- [ ] Bookmarks/outline
- [ ] Forms (campos rellenables)
---
## API Actual
### API Nueva (Pdf)
```zig
const zpdf = @import("zpdf");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Crear documento
var doc = zpdf.Pdf.init(allocator, .{
.page_size = .a4,
.orientation = .portrait,
});
defer doc.deinit();
// Metadatos
doc.setTitle("Mi Documento");
doc.setAuthor("zpdf");
// Agregar pagina
var page = try doc.addPage(.{});
// Configurar fuente y posicion
try page.setFont(.helvetica_bold, 24);
page.setXY(50, 800);
page.setMargins(50, 50, 50);
// cell() - celda simple
try page.cell(0, 30, "Titulo", zpdf.Border.none, .center, false);
page.ln(35);
// Tabla con cells
try page.setFont(.helvetica, 12);
page.setFillColor(zpdf.Color.light_gray);
try page.cell(150, 20, "Columna 1", zpdf.Border.all, .center, true);
try page.cell(150, 20, "Columna 2", zpdf.Border.all, .center, true);
page.ln(null);
// multiCell - texto con word wrap
const texto_largo = "Este es un texto largo que se ajustara automaticamente...";
try page.multiCell(400, null, texto_largo, zpdf.Border.all, .left, false);
// Guardar
try doc.save("documento.pdf");
}
```
### API Legacy (Document)
```zig
const pdf = @import("zpdf");
var doc = pdf.Document.init(allocator);
defer doc.deinit();
var page = try doc.addPage(.a4);
try page.setFont(.helvetica_bold, 24);
try page.drawText(50, 750, "Titulo");
try doc.saveToFile("documento.pdf");
```
### Sistema de Texto
```zig
// cell(width, height, text, border, align, fill)
// width=0 extiende hasta margen derecho
// width=null ajusta al ancho del texto
try page.cell(100, 20, "Hello", Border.all, .left, false);
try page.cell(0, 20, "Full width", Border.none, .center, true);
// cellAdvanced - control de posicion despues de la celda
try page.cellAdvanced(100, 20, "A", Border.all, .left, false, .right); // mover a la derecha
try page.cellAdvanced(100, 20, "B", Border.all, .left, false, .next_line); // nueva linea
try page.cellAdvanced(100, 20, "C", Border.all, .left, false, .below); // debajo (mismo X)
// multiCell - word wrap automatico
try page.multiCell(200, 15, "Texto largo que se ajusta automaticamente al ancho especificado.", Border.all, .left, true);
// ln(height) - salto de linea
page.ln(20); // salto de 20 puntos
page.ln(null); // salto del tamano de fuente actual
// getStringWidth - ancho del texto
const width = page.getStringWidth("Hello World");
```
### Bordes
```zig
const Border = packed struct {
left: bool,
top: bool,
right: bool,
bottom: bool,
};
Border.none // sin bordes
Border.all // todos los bordes
Border{ .left = true, .bottom = true } // bordes especificos
Border.fromInt(0b1111) // desde entero (LTRB)
```
### Alineacion
```zig
const Align = enum { left, center, right };
try page.cell(100, 20, "Left", Border.all, .left, false);
try page.cell(100, 20, "Center", Border.all, .center, false);
try page.cell(100, 20, "Right", Border.all, .right, false);
```
### Colores
```zig
// Predefinidos
zpdf.Color.black
zpdf.Color.white
zpdf.Color.red
zpdf.Color.green
zpdf.Color.blue
zpdf.Color.light_gray
zpdf.Color.medium_gray
// RGB (0-255)
zpdf.Color.rgb(41, 98, 255)
// Hex
zpdf.Color.hex(0xFF8000)
// CMYK (0.0-1.0)
zpdf.Color.cmyk(0.0, 1.0, 1.0, 0.0)
// Grayscale (0.0-1.0)
zpdf.Color.gray(0.5)
```
---
## 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
# Ejecutar ejemplos
$ZIG build && ./zig-out/bin/hello
$ZIG build && ./zig-out/bin/invoice
$ZIG build && ./zig-out/bin/text_demo
```
---
## Fuentes Type1 Built-in
PDF incluye 14 fuentes estandar que no necesitan embeber:
| Familia | Variantes |
|---------|-----------|
| Helvetica | helvetica, helvetica_bold, helvetica_oblique, helvetica_bold_oblique |
| Times | times_roman, times_bold, times_italic, times_bold_italic |
| Courier | courier, courier_bold, courier_oblique, courier_bold_oblique |
| Otros | symbol, zapf_dingbats |
---
## Tamanos de Pagina
| Nombre | Puntos | Milimetros |
|--------|--------|------------|
| A4 | 595 x 842 | 210 x 297 |
| A3 | 842 x 1191 | 297 x 420 |
| A5 | 420 x 595 | 148 x 210 |
| Letter | 612 x 792 | 216 x 279 |
| Legal | 612 x 1008 | 216 x 356 |
---
## Equipo y Metodologia
### Normas de Trabajo Centralizadas
**IMPORTANTE**: Todas las normas de trabajo estan en:
```
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/
```
### Control de Versiones
```bash
# Remote
git remote: git@git.reugenio.com:reugenio/zpdf.git
# Branches
main # Codigo estable
```
---
## Historial de Desarrollo
### 2025-12-08 - v0.2 (Sistema de Texto Completo)
- Refactoring modular completo (fonts/, graphics/, objects/, output/)
- Arreglados errores Zig 0.15 (ArrayListUnmanaged API)
- Sistema de texto completo:
- cell() con bordes, relleno, alineacion
- cellAdvanced() con control de posicion
- multiCell() con word wrap automatico
- ln() para saltos de linea
- getStringWidth() para calcular anchos
- Margenes de pagina configurables
- Nueva API Pdf (mas limpia que Document legacy)
- 52 tests unitarios pasando
- Nuevo ejemplo: text_demo.zig
### 2025-12-08 - v0.1 (Core Funcional)
- Estructura inicial del proyecto
- Document, Page, Color, Font, PageSize types
- Texto con 14 fuentes Type1 standard
- Graficos: lineas, rectangulos (stroke, fill, both)
- Colores RGB
- Serializacion PDF 1.4 correcta
- 6 tests unitarios pasando
- Ejemplos: hello.zig, invoice.zig funcionales
---
## Referencias
- **fpdf2 (Python)**: https://github.com/py-pdf/fpdf2 - Fuente principal
- **PDF 1.4 Spec**: https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/pdfreference1.4.pdf
- **pdf-nano (Zig)**: https://github.com/GregorBudweiser/pdf-nano
---
**zpdf - Generador PDF para Zig**
*v0.2 - 2025-12-08*