Document that TTF font subsetting is not yet implemented - entire font files are embedded rather than just glyphs used. Planned for future. Reported by: Gemini audit (2025-12-14) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
943 lines
22 KiB
Markdown
943 lines
22 KiB
Markdown
# zcatpdf - PDF Generation Library for Zig
|
|
|
|
A pure Zig library for creating PDF documents with minimal dependencies.
|
|
|
|
```zig
|
|
const zcatpdf = @import("zcatpdf");
|
|
|
|
pub fn main() !void {
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{});
|
|
defer pdf.deinit();
|
|
|
|
var page = try pdf.addPage(.{});
|
|
try page.setFont(.helvetica_bold, 24);
|
|
try page.drawText(50, 750, "Hello, PDF!");
|
|
|
|
try pdf.save("hello.pdf");
|
|
}
|
|
```
|
|
|
|
## Features
|
|
|
|
- **Pure Zig** - Minimal dependencies (only libdeflate for compression)
|
|
- **PDF 1.4** - Compatible with all PDF readers
|
|
- **Complete text system** - Fonts, alignment, word wrap, cells
|
|
- **Images** - JPEG and PNG (with alpha/transparency)
|
|
- **Vector graphics** - Lines, curves, shapes, gradients
|
|
- **Tables** - Helper for formatted tables
|
|
- **Barcodes** - Code128 (1D) and QR Code (2D)
|
|
- **Links** - Clickable URLs and internal page links
|
|
- **Bookmarks** - Document outline/navigation
|
|
- **Transformations** - Rotate, scale, translate, skew
|
|
- **Transparency** - Fill and stroke opacity
|
|
- **Templates** - Reusable document layouts
|
|
- **Markdown** - Styled text with Markdown syntax
|
|
|
|
## Installation
|
|
|
|
Add zcatpdf to your `build.zig.zon`:
|
|
|
|
```zig
|
|
.dependencies = .{
|
|
.zcatpdf = .{
|
|
.url = "https://git.reugenio.com/reugenio/zcatpdf/archive/v1.0.tar.gz",
|
|
.hash = "...",
|
|
},
|
|
},
|
|
```
|
|
|
|
In your `build.zig`:
|
|
|
|
```zig
|
|
const zcatpdf_dep = b.dependency("zcatpdf", .{
|
|
.target = target,
|
|
.optimize = optimize,
|
|
});
|
|
exe.root_module.addImport("zcatpdf", zcatpdf_dep.module("zcatpdf"));
|
|
```
|
|
|
|
## Quick Reference
|
|
|
|
### Table of Contents
|
|
|
|
1. [Document Creation](#1-document-creation)
|
|
2. [Pages](#2-pages)
|
|
3. [Text](#3-text)
|
|
4. [Fonts](#4-fonts)
|
|
5. [Colors](#5-colors)
|
|
6. [Graphics](#6-graphics)
|
|
7. [Images](#7-images)
|
|
8. [Tables](#8-tables)
|
|
9. [Links](#9-links)
|
|
10. [Bookmarks](#10-bookmarks)
|
|
11. [Barcodes](#11-barcodes)
|
|
12. [Transformations](#12-transformations)
|
|
13. [Transparency](#13-transparency)
|
|
14. [Gradients](#14-gradients)
|
|
15. [Templates](#15-templates)
|
|
16. [Markdown](#16-markdown)
|
|
17. [Compression](#17-compression)
|
|
|
|
---
|
|
|
|
## 1. Document Creation
|
|
|
|
**File:** `src/pdf.zig`
|
|
|
|
```zig
|
|
const zcatpdf = @import("zcatpdf");
|
|
|
|
// Create document with default settings
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{});
|
|
defer pdf.deinit();
|
|
|
|
// Create document with options
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{
|
|
.page_size = .a4,
|
|
.orientation = .portrait,
|
|
.unit = .pt,
|
|
});
|
|
|
|
// Set metadata
|
|
pdf.setTitle("Document Title");
|
|
pdf.setAuthor("Author Name");
|
|
pdf.setSubject("Subject");
|
|
pdf.setKeywords("keyword1, keyword2");
|
|
pdf.setCreator("Application Name");
|
|
|
|
// Save to file
|
|
try pdf.save("output.pdf");
|
|
|
|
// Or get as bytes
|
|
const data = try pdf.output();
|
|
defer allocator.free(data);
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Pdf` | `src/pdf.zig` | Main document struct |
|
|
| `Config` | `src/pdf.zig` | Document configuration |
|
|
|
|
---
|
|
|
|
## 2. Pages
|
|
|
|
**File:** `src/page.zig`, `src/objects/base.zig`
|
|
|
|
```zig
|
|
// Add page with document defaults
|
|
var page = try pdf.addPage(.{});
|
|
|
|
// Add page with specific size
|
|
var page = try pdf.addPage(.{ .size = .letter });
|
|
|
|
// Add page with custom dimensions (points)
|
|
var page = try pdf.addPageCustom(612, 792);
|
|
|
|
// Page sizes available
|
|
.a3 // 842 x 1191 pt
|
|
.a4 // 595 x 842 pt
|
|
.a5 // 420 x 595 pt
|
|
.letter // 612 x 792 pt
|
|
.legal // 612 x 1008 pt
|
|
|
|
// Orientations
|
|
.portrait
|
|
.landscape
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Page` | `src/page.zig` | Page struct with drawing methods |
|
|
| `PageSize` | `src/objects/base.zig` | Standard page sizes |
|
|
| `Orientation` | `src/objects/base.zig` | Portrait/Landscape |
|
|
|
|
---
|
|
|
|
## 3. Text
|
|
|
|
**File:** `src/page.zig`
|
|
|
|
```zig
|
|
// Simple text at position
|
|
try page.drawText(x, y, "Hello World");
|
|
|
|
// Cell with border and background
|
|
try page.cell(width, height, "Text", Border.all, .center, true);
|
|
|
|
// Multi-line text with word wrap
|
|
try page.multiCell(width, line_height, long_text, Border.none, .left, false);
|
|
|
|
// Get/set cursor position
|
|
const x = page.getX();
|
|
const y = page.getY();
|
|
page.setXY(100, 500);
|
|
|
|
// Line break
|
|
page.ln(20); // Move down 20 points
|
|
```
|
|
|
|
### Cell Parameters
|
|
|
|
```zig
|
|
try page.cell(
|
|
width, // f32 - Cell width
|
|
height, // f32 - Cell height
|
|
text, // []const u8 - Text content
|
|
border, // Border - Border style
|
|
align, // Align - Text alignment
|
|
fill, // bool - Fill background
|
|
);
|
|
```
|
|
|
|
### Border Options
|
|
|
|
```zig
|
|
Border.none // No border
|
|
Border.all // All sides
|
|
Border.left // Left only
|
|
Border.right // Right only
|
|
Border.top // Top only
|
|
Border.bottom // Bottom only
|
|
// Combine with Border.combine()
|
|
```
|
|
|
|
### Alignment
|
|
|
|
```zig
|
|
.left
|
|
.center
|
|
.right
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Fonts
|
|
|
|
**File:** `src/fonts/type1.zig`, `src/fonts/ttf.zig`
|
|
|
|
```zig
|
|
// Set font
|
|
try page.setFont(.helvetica, 12);
|
|
try page.setFont(.helvetica_bold, 14);
|
|
try page.setFont(.times_roman, 11);
|
|
try page.setFont(.courier, 10);
|
|
|
|
// Calculate string width
|
|
const width = zcatpdf.Font.helvetica.stringWidth("Hello", 12.0);
|
|
```
|
|
|
|
### Available Fonts (Type1 built-in)
|
|
|
|
| Font | Constant |
|
|
|------|----------|
|
|
| Helvetica | `.helvetica` |
|
|
| Helvetica Bold | `.helvetica_bold` |
|
|
| Helvetica Oblique | `.helvetica_oblique` |
|
|
| Helvetica Bold Oblique | `.helvetica_bold_oblique` |
|
|
| Times Roman | `.times_roman` |
|
|
| Times Bold | `.times_bold` |
|
|
| Times Italic | `.times_italic` |
|
|
| Times Bold Italic | `.times_bold_italic` |
|
|
| Courier | `.courier` |
|
|
| Courier Bold | `.courier_bold` |
|
|
| Courier Oblique | `.courier_oblique` |
|
|
| Courier Bold Oblique | `.courier_bold_oblique` |
|
|
| Symbol | `.symbol` |
|
|
| ZapfDingbats | `.zapf_dingbats` |
|
|
|
|
### TrueType Fonts (parsing only)
|
|
|
|
```zig
|
|
// Load TTF file
|
|
const font_data = try std.fs.cwd().readFileAlloc(allocator, "font.ttf", 10_000_000);
|
|
var ttf = try zcatpdf.TrueTypeFont.parse(allocator, font_data);
|
|
defer ttf.deinit();
|
|
|
|
// Get font info
|
|
std.debug.print("Family: {s}\n", .{ttf.family_name});
|
|
std.debug.print("Ascender: {d}\n", .{ttf.ascender});
|
|
|
|
// Calculate string width
|
|
const width = ttf.stringWidth("Hello", 12.0);
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Font` | `src/fonts/type1.zig` | Type1 font enum |
|
|
| `TrueTypeFont` | `src/fonts/ttf.zig` | TTF parser |
|
|
|
|
---
|
|
|
|
## 5. Colors
|
|
|
|
**File:** `src/graphics/color.zig`
|
|
|
|
```zig
|
|
// Set colors
|
|
page.setFillColor(zcatpdf.Color.red);
|
|
page.setStrokeColor(zcatpdf.Color.blue);
|
|
|
|
// RGB (0-255)
|
|
page.setFillColor(zcatpdf.Color.rgb(255, 128, 0));
|
|
|
|
// Hex
|
|
page.setFillColor(zcatpdf.Color.hex(0xFF8000));
|
|
|
|
// Grayscale (0.0-1.0)
|
|
page.setFillColor(zcatpdf.Color.gray(0.5));
|
|
|
|
// CMYK (0.0-1.0)
|
|
page.setFillColor(zcatpdf.Color.cmyk(0, 1, 1, 0)); // Red
|
|
```
|
|
|
|
### Predefined Colors
|
|
|
|
```zig
|
|
Color.black
|
|
Color.white
|
|
Color.red
|
|
Color.green
|
|
Color.blue
|
|
Color.yellow
|
|
Color.cyan
|
|
Color.magenta
|
|
Color.orange
|
|
Color.purple
|
|
Color.pink
|
|
Color.brown
|
|
Color.gray
|
|
Color.light_gray
|
|
Color.dark_gray
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Color` | `src/graphics/color.zig` | Color struct (RGB, CMYK, Gray) |
|
|
|
|
---
|
|
|
|
## 6. Graphics
|
|
|
|
**File:** `src/page.zig`, `src/content_stream.zig`
|
|
|
|
### Lines
|
|
|
|
```zig
|
|
try page.setLineWidth(2.0);
|
|
try page.drawLine(x1, y1, x2, y2);
|
|
```
|
|
|
|
### Rectangles
|
|
|
|
```zig
|
|
// Stroke only
|
|
try page.drawRect(x, y, width, height);
|
|
|
|
// Fill only
|
|
try page.fillRect(x, y, width, height);
|
|
|
|
// Fill and stroke
|
|
try page.fillAndStrokeRect(x, y, width, height);
|
|
```
|
|
|
|
### Circles and Ellipses
|
|
|
|
```zig
|
|
// Circle
|
|
try page.drawCircle(cx, cy, radius);
|
|
try page.fillCircle(cx, cy, radius);
|
|
|
|
// Ellipse
|
|
try page.drawEllipse(cx, cy, rx, ry);
|
|
try page.fillEllipse(cx, cy, rx, ry);
|
|
|
|
// Arc
|
|
try page.drawArc(cx, cy, rx, ry, start_angle, end_angle);
|
|
```
|
|
|
|
### Bezier Curves
|
|
|
|
```zig
|
|
// Cubic Bezier
|
|
try page.drawBezier(x0, y0, x1, y1, x2, y2, x3, y3);
|
|
|
|
// Quadratic Bezier
|
|
try page.drawQuadBezier(x0, y0, x1, y1, x2, y2);
|
|
```
|
|
|
|
### Line Style
|
|
|
|
```zig
|
|
try page.setLineWidth(2.0);
|
|
try page.setLineCap(.round); // .butt, .round, .square
|
|
try page.setLineJoin(.round); // .miter, .round, .bevel
|
|
try page.setDashPattern(&.{5, 3}, 0); // [dash, gap], phase
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `ContentStream` | `src/content_stream.zig` | Low-level PDF operators |
|
|
| `LineCap` | `src/content_stream.zig` | Line cap styles |
|
|
| `LineJoin` | `src/content_stream.zig` | Line join styles |
|
|
|
|
---
|
|
|
|
## 7. Images
|
|
|
|
**File:** `src/images/jpeg.zig`, `src/images/png.zig`, `src/images/image_info.zig`
|
|
|
|
```zig
|
|
// Load JPEG
|
|
const jpeg_idx = try pdf.addJpegImageFromFile("photo.jpg");
|
|
|
|
// Load PNG
|
|
const png_idx = try pdf.addPngImageFromFile("logo.png");
|
|
|
|
// Load from memory
|
|
const img_idx = try pdf.addJpegImage(jpeg_bytes);
|
|
const img_idx = try pdf.addPngImage(png_bytes);
|
|
|
|
// Get image info
|
|
const info = pdf.getImage(img_idx).?;
|
|
std.debug.print("Size: {d}x{d}\n", .{info.width, info.height});
|
|
|
|
// Draw image at position with size
|
|
try page.image(img_idx, info, x, y, width, height);
|
|
|
|
// Draw image preserving aspect ratio
|
|
try page.imageFit(img_idx, info, x, y, max_width, max_height);
|
|
```
|
|
|
|
### Supported Formats
|
|
|
|
| Format | Features |
|
|
|--------|----------|
|
|
| JPEG | RGB, Grayscale |
|
|
| PNG | RGB, RGBA (with alpha), Grayscale, Indexed |
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `ImageInfo` | `src/images/image_info.zig` | Image metadata |
|
|
| `ImageFormat` | `src/images/image_info.zig` | JPEG, PNG enum |
|
|
|
|
---
|
|
|
|
## 8. Tables
|
|
|
|
**File:** `src/table.zig`
|
|
|
|
```zig
|
|
const col_widths = [_]f32{ 200, 100, 100, 100 };
|
|
|
|
var table = zcatpdf.Table.init(page, .{
|
|
.x = 50,
|
|
.y = 700,
|
|
.col_widths = &col_widths,
|
|
.row_height = 20,
|
|
.header_bg_color = zcatpdf.Color.hex(0xE0E0E0),
|
|
.border = true,
|
|
});
|
|
|
|
// Header row
|
|
try table.header(&.{ "Description", "Qty", "Price", "Total" });
|
|
|
|
// Data rows
|
|
try table.row(&.{ "Product A", "2", "$10.00", "$20.00" });
|
|
try table.row(&.{ "Product B", "1", "$25.00", "$25.00" });
|
|
|
|
// Footer row
|
|
try table.footer(&.{ "", "", "Total:", "$45.00" });
|
|
```
|
|
|
|
### Table Options
|
|
|
|
```zig
|
|
TableOptions{
|
|
.x = 50, // X position
|
|
.y = 700, // Y position
|
|
.col_widths = &widths, // Column widths array
|
|
.row_height = 20, // Row height
|
|
.header_bg_color = Color.gray, // Header background
|
|
.row_bg_color = null, // Row background
|
|
.alt_row_bg_color = null, // Alternating row background
|
|
.border = true, // Draw borders
|
|
.header_font = .helvetica_bold, // Header font
|
|
.body_font = .helvetica, // Body font
|
|
.font_size = 10, // Font size
|
|
}
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Table` | `src/table.zig` | Table helper |
|
|
| `TableOptions` | `src/table.zig` | Table configuration |
|
|
|
|
---
|
|
|
|
## 9. Links
|
|
|
|
**File:** `src/links.zig`, `src/page.zig`
|
|
|
|
```zig
|
|
// URL link with visual styling (blue + underline)
|
|
_ = try page.urlLink(x, y, "Click here", "https://example.com");
|
|
|
|
// URL link from current position
|
|
_ = try page.writeUrlLink("Visit website", "https://example.com");
|
|
|
|
// Internal link (jump to page)
|
|
try page.addInternalLink(target_page, x, y, width, height);
|
|
|
|
// URL link without visual (just annotation)
|
|
try page.addUrlLink("https://example.com", x, y, width, height);
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Link` | `src/links.zig` | Link struct |
|
|
| `PageLinks` | `src/links.zig` | Page link collection |
|
|
|
|
---
|
|
|
|
## 10. Bookmarks
|
|
|
|
**File:** `src/outline.zig`
|
|
|
|
```zig
|
|
// Add bookmark to page
|
|
try pdf.addBookmark("Chapter 1", 0); // page index 0
|
|
|
|
// Add bookmark with Y position
|
|
try pdf.addBookmarkAt("Section 1.1", 0, 500);
|
|
```
|
|
|
|
Bookmarks appear in the PDF reader's sidebar for navigation.
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Outline` | `src/outline.zig` | Document outline |
|
|
| `OutlineItem` | `src/outline.zig` | Single bookmark |
|
|
|
|
---
|
|
|
|
## 11. Barcodes
|
|
|
|
**File:** `src/barcodes/code128.zig`, `src/barcodes/qr.zig`
|
|
|
|
### Code128 (1D)
|
|
|
|
```zig
|
|
// Basic barcode
|
|
try page.drawCode128(x, y, "ABC-12345", height, module_width);
|
|
|
|
// Barcode with text below
|
|
try page.drawCode128WithText(x, y, "ABC-12345", height, module_width, show_text);
|
|
```
|
|
|
|
### QR Code (2D)
|
|
|
|
```zig
|
|
try page.drawQRCode(x, y, "https://example.com", size, error_correction);
|
|
|
|
// Error correction levels
|
|
zcatpdf.QRCode.ErrorCorrection.L // 7% recovery
|
|
zcatpdf.QRCode.ErrorCorrection.M // 15% recovery
|
|
zcatpdf.QRCode.ErrorCorrection.Q // 25% recovery
|
|
zcatpdf.QRCode.ErrorCorrection.H // 30% recovery
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Code128` | `src/barcodes/code128.zig` | Code128 encoder |
|
|
| `QRCode` | `src/barcodes/qr.zig` | QR Code encoder |
|
|
|
|
---
|
|
|
|
## 12. Transformations
|
|
|
|
**File:** `src/page.zig`
|
|
|
|
```zig
|
|
// Save state before transforming
|
|
try page.saveState();
|
|
|
|
// Rotate around point (degrees)
|
|
try page.rotate(45, center_x, center_y);
|
|
|
|
// Scale from point
|
|
try page.scale(2.0, 1.5, origin_x, origin_y);
|
|
|
|
// Translate
|
|
try page.translate(100, 50);
|
|
|
|
// Skew (degrees)
|
|
try page.skew(15, 0); // X skew
|
|
try page.skew(0, 10); // Y skew
|
|
|
|
// Custom transformation matrix
|
|
try page.transform(a, b, c, d, e, f);
|
|
|
|
// Restore state
|
|
try page.restoreState();
|
|
```
|
|
|
|
**Important:** Always use `saveState()`/`restoreState()` to limit transformation scope.
|
|
|
|
---
|
|
|
|
## 13. Transparency
|
|
|
|
**File:** `src/graphics/extgstate.zig`, `src/page.zig`
|
|
|
|
```zig
|
|
// Set fill opacity (0.0 = transparent, 1.0 = opaque)
|
|
try page.setFillOpacity(0.5);
|
|
|
|
// Set stroke opacity
|
|
try page.setStrokeOpacity(0.75);
|
|
|
|
// Set both at once
|
|
try page.setOpacity(0.3);
|
|
|
|
// Reset to fully opaque
|
|
try page.setOpacity(1.0);
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `ExtGState` | `src/graphics/extgstate.zig` | Extended graphics state |
|
|
|
|
---
|
|
|
|
## 14. Gradients
|
|
|
|
**File:** `src/graphics/gradient.zig`, `src/page.zig`
|
|
|
|
### Linear Gradients
|
|
|
|
```zig
|
|
// Horizontal gradient
|
|
try page.linearGradientRect(x, y, width, height,
|
|
zcatpdf.Color.red, zcatpdf.Color.blue, .horizontal);
|
|
|
|
// Vertical gradient
|
|
try page.linearGradientRect(x, y, width, height,
|
|
zcatpdf.Color.green, zcatpdf.Color.yellow, .vertical);
|
|
|
|
// Diagonal gradient
|
|
try page.linearGradientRect(x, y, width, height,
|
|
zcatpdf.Color.purple, zcatpdf.Color.cyan, .diagonal);
|
|
```
|
|
|
|
### Radial Gradients
|
|
|
|
```zig
|
|
// Circle gradient (center to edge)
|
|
try page.radialGradientCircle(cx, cy, radius,
|
|
zcatpdf.Color.white, zcatpdf.Color.blue);
|
|
|
|
// Ellipse gradient
|
|
try page.radialGradientEllipse(cx, cy, rx, ry,
|
|
zcatpdf.Color.yellow, zcatpdf.Color.red);
|
|
```
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Gradient` | `src/graphics/gradient.zig` | Gradient definitions |
|
|
| `LinearGradient` | `src/graphics/gradient.zig` | Linear gradient |
|
|
| `RadialGradient` | `src/graphics/gradient.zig` | Radial gradient |
|
|
| `GradientDirection` | `src/page.zig` | horizontal, vertical, diagonal |
|
|
|
|
---
|
|
|
|
## 15. Templates
|
|
|
|
**File:** `src/template/template.zig`
|
|
|
|
Templates define reusable document layouts with named regions.
|
|
|
|
```zig
|
|
// Use predefined invoice template
|
|
var tmpl = try zcatpdf.Template.invoiceTemplate(allocator);
|
|
defer tmpl.deinit();
|
|
|
|
// Or create custom template
|
|
var tmpl = zcatpdf.Template.init(allocator, "custom", 595, 842);
|
|
defer tmpl.deinit();
|
|
|
|
try tmpl.defineRegion("header", .{
|
|
.x = 50,
|
|
.y = 750,
|
|
.width = 495,
|
|
.height = 80,
|
|
.region_type = .text,
|
|
});
|
|
|
|
// Use regions to position content
|
|
if (tmpl.getRegion("header")) |region| {
|
|
try page.drawText(region.x, region.y, "Header Content");
|
|
}
|
|
```
|
|
|
|
### Predefined Templates
|
|
|
|
- `Template.invoiceTemplate()` - Invoice with header, customer, items, totals, footer
|
|
- `Template.letterTemplate()` - Letter with sender, recipient, date, subject, body, signature
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `Template` | `src/template/template.zig` | Template struct |
|
|
| `TemplateRegion` | `src/template/template.zig` | Region definition |
|
|
| `RegionType` | `src/template/template.zig` | text, image, table, custom |
|
|
| `FixedContent` | `src/template/template.zig` | Repeating content |
|
|
|
|
---
|
|
|
|
## 16. Markdown
|
|
|
|
**File:** `src/markdown/markdown.zig`
|
|
|
|
Parse Markdown-style text and render with appropriate styles.
|
|
|
|
```zig
|
|
var renderer = zcatpdf.MarkdownRenderer.init(allocator);
|
|
defer renderer.deinit();
|
|
|
|
try renderer.parse(
|
|
\\# Heading 1
|
|
\\
|
|
\\This is **bold** and *italic* text.
|
|
\\
|
|
\\- Bullet item
|
|
\\- Another item
|
|
\\
|
|
\\[Link text](https://example.com)
|
|
);
|
|
|
|
// Render to PDF
|
|
for (renderer.getLines()) |line| {
|
|
for (line.spans) |span| {
|
|
const font = zcatpdf.MarkdownRenderer.fontForStyle(span.style);
|
|
try page.setFont(font, span.font_size orelse 12);
|
|
|
|
if (span.color) |color| {
|
|
page.setFillColor(zcatpdf.Color.hex(color));
|
|
}
|
|
|
|
try page.drawText(x, y, span.text);
|
|
x += font.stringWidth(span.text, font_size);
|
|
}
|
|
y -= line_height;
|
|
}
|
|
```
|
|
|
|
### Supported Syntax
|
|
|
|
| Syntax | Result |
|
|
|--------|--------|
|
|
| `**text**` or `__text__` | **Bold** |
|
|
| `*text*` or `_text_` | *Italic* |
|
|
| `***text***` | ***Bold + Italic*** |
|
|
| `~~text~~` | ~~Strikethrough~~ |
|
|
| `[text](url)` | Link |
|
|
| `# Heading` | Heading 1 |
|
|
| `## Heading` | Heading 2 |
|
|
| `### Heading` | Heading 3 |
|
|
| `- item` | Bullet list |
|
|
| `1. item` | Numbered list |
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `MarkdownRenderer` | `src/markdown/markdown.zig` | Parser/renderer |
|
|
| `TextSpan` | `src/markdown/markdown.zig` | Styled text span |
|
|
| `SpanStyle` | `src/markdown/markdown.zig` | Style flags |
|
|
|
|
---
|
|
|
|
## 17. Compression
|
|
|
|
**File:** `src/compression/zlib.zig`, `src/output/producer.zig`
|
|
|
|
```zig
|
|
// Configure compression when creating document
|
|
var pdf = zcatpdf.Pdf.init(allocator, .{
|
|
.compression = .{
|
|
.enabled = true,
|
|
.level = 6, // 0-12, higher = better compression
|
|
.min_size = 256, // Don't compress streams smaller than this
|
|
},
|
|
});
|
|
```
|
|
|
|
### Compression Options
|
|
|
|
| Option | Default | Description |
|
|
|--------|---------|-------------|
|
|
| `enabled` | `true` | Enable FlateDecode compression |
|
|
| `level` | `6` | Compression level (0-12) |
|
|
| `min_size` | `256` | Minimum stream size to compress |
|
|
|
|
### Types
|
|
|
|
| Type | File | Description |
|
|
|------|------|-------------|
|
|
| `CompressionOptions` | `src/output/producer.zig` | Compression config |
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
```
|
|
src/
|
|
├── root.zig # Public exports
|
|
├── pdf.zig # Pdf document facade
|
|
├── page.zig # Page with drawing methods
|
|
├── content_stream.zig # PDF operators
|
|
├── table.zig # Table helper
|
|
├── pagination.zig # Page numbers, headers, footers
|
|
├── links.zig # Link types
|
|
├── outline.zig # Bookmarks
|
|
├── fonts/
|
|
│ ├── mod.zig # Font exports
|
|
│ ├── type1.zig # 14 Type1 fonts + metrics
|
|
│ └── ttf.zig # TrueType parser
|
|
├── graphics/
|
|
│ ├── mod.zig # Graphics exports
|
|
│ ├── color.zig # Color types
|
|
│ ├── extgstate.zig # Transparency (ExtGState)
|
|
│ └── gradient.zig # Linear/Radial gradients
|
|
├── images/
|
|
│ ├── mod.zig # Image exports
|
|
│ ├── image_info.zig # ImageInfo struct
|
|
│ ├── jpeg.zig # JPEG parser
|
|
│ └── png.zig # PNG parser
|
|
├── barcodes/
|
|
│ ├── mod.zig # Barcode exports
|
|
│ ├── code128.zig # Code128 encoder
|
|
│ └── qr.zig # QR Code encoder
|
|
├── compression/
|
|
│ ├── mod.zig # Compression exports
|
|
│ └── zlib.zig # libdeflate wrapper
|
|
├── objects/
|
|
│ ├── mod.zig # Object exports
|
|
│ └── base.zig # PageSize, Orientation
|
|
├── output/
|
|
│ ├── mod.zig # Output exports
|
|
│ └── producer.zig # PDF serialization
|
|
├── security/
|
|
│ ├── mod.zig # Security exports
|
|
│ ├── rc4.zig # RC4 cipher
|
|
│ └── encryption.zig # PDF encryption
|
|
├── forms/
|
|
│ ├── mod.zig # Forms exports
|
|
│ └── field.zig # TextField, CheckBox
|
|
├── svg/
|
|
│ ├── mod.zig # SVG exports
|
|
│ └── parser.zig # SVG parser
|
|
├── template/
|
|
│ ├── mod.zig # Template exports
|
|
│ └── template.zig # Template definitions
|
|
└── markdown/
|
|
├── mod.zig # Markdown exports
|
|
└── markdown.zig # Markdown parser
|
|
```
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
16 example files in `examples/`:
|
|
|
|
| File | Description |
|
|
|------|-------------|
|
|
| `hello.zig` | Minimal PDF |
|
|
| `invoice.zig` | Complete invoice |
|
|
| `text_demo.zig` | Text system (cell, multiCell) |
|
|
| `image_demo.zig` | JPEG and PNG images |
|
|
| `table_demo.zig` | Table helper |
|
|
| `pagination_demo.zig` | Multi-page with page numbers |
|
|
| `links_demo.zig` | Clickable links |
|
|
| `bookmarks_demo.zig` | Document outline |
|
|
| `curves_demo.zig` | Bezier, circles, arcs |
|
|
| `transforms_demo.zig` | Rotate, scale, skew |
|
|
| `transparency_demo.zig` | Opacity/alpha |
|
|
| `gradient_demo.zig` | Linear and radial gradients |
|
|
| `barcode_demo.zig` | Code128 and QR codes |
|
|
| `ttf_demo.zig` | TrueType font parsing |
|
|
| `template_demo.zig` | Document templates |
|
|
| `markdown_demo.zig` | Markdown styled text |
|
|
|
|
### Run Examples
|
|
|
|
```bash
|
|
# Build all
|
|
zig build
|
|
|
|
# Run specific example
|
|
./zig-out/bin/hello
|
|
./zig-out/bin/invoice
|
|
./zig-out/bin/barcode_demo
|
|
# etc.
|
|
```
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
- **TTF Font Subsetting**: When embedding TrueType fonts, the entire font file is included rather than just the glyphs used. This can result in larger PDF files when using custom fonts. Font subsetting is planned for a future version.
|
|
|
|
---
|
|
|
|
## Building
|
|
|
|
```bash
|
|
# Build library
|
|
zig build
|
|
|
|
# Run tests
|
|
zig build test
|
|
|
|
# Build specific example
|
|
zig build hello
|
|
```
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
MIT
|
|
|
|
---
|
|
|
|
## Version
|
|
|
|
**v1.0** - Feature Complete (2025-12-09)
|