Major features added since v0.5: - PNG support with alpha/transparency (soft masks) - FlateDecode compression via libdeflate-zig - Bookmarks/Outline for document navigation - Bezier curves, circles, ellipses, arcs - Transformations (rotate, scale, translate, skew) - Transparency/opacity (fill and stroke alpha) - Linear and radial gradients (Shading Patterns) - Code128 (1D) and QR Code (2D) barcodes - TrueType font parsing (metrics, glyph widths) - RC4 encryption module (40/128-bit) - AcroForms module (TextField, CheckBox) - SVG import (basic shapes and paths) - Template system (reusable layouts) - Markdown styling (bold, italic, links, headings, lists) Documentation: - README.md: Complete API reference with code examples - FUTURE_IMPROVEMENTS.md: Detailed roadmap for future development - CLAUDE.md: Updated to v1.0 release status Stats: - 125+ unit tests passing - 16 demo examples - 46 source files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
247 lines
8.8 KiB
Zig
247 lines
8.8 KiB
Zig
//! Curves Demo - Bezier Curves, Circles, Ellipses, and Arcs
|
|
//!
|
|
//! Demonstrates the curve drawing capabilities of zpdf including:
|
|
//! - Cubic and quadratic Bezier curves
|
|
//! - Circles and ellipses
|
|
//! - Arcs
|
|
|
|
const std = @import("std");
|
|
const pdf = @import("zpdf");
|
|
|
|
pub fn main() !void {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer _ = gpa.deinit();
|
|
const allocator = gpa.allocator();
|
|
|
|
std.debug.print("zpdf - Curves Demo\n", .{});
|
|
|
|
var doc = pdf.Pdf.init(allocator, .{});
|
|
defer doc.deinit();
|
|
|
|
doc.setTitle("Curves Demo");
|
|
doc.setAuthor("zpdf");
|
|
|
|
// =========================================================================
|
|
// Page 1: Bezier Curves
|
|
// =========================================================================
|
|
{
|
|
const page = try doc.addPage(.{});
|
|
|
|
// Title
|
|
try page.setFont(.helvetica_bold, 24);
|
|
page.setFillColor(pdf.Color.rgb(41, 98, 255));
|
|
try page.drawText(50, 780, "Bezier Curves");
|
|
|
|
try page.setFont(.helvetica, 11);
|
|
page.setFillColor(pdf.Color.black);
|
|
try page.drawText(50, 755, "Cubic and quadratic Bezier curves for smooth paths");
|
|
|
|
// Cubic Bezier curve
|
|
try page.setLineWidth(2);
|
|
page.setStrokeColor(pdf.Color.rgb(220, 20, 60)); // Crimson
|
|
|
|
// Draw a smooth S-curve
|
|
try page.drawBezier(
|
|
100, 650, // Start point
|
|
150, 700, // Control point 1
|
|
250, 550, // Control point 2
|
|
300, 600, // End point
|
|
);
|
|
|
|
// Label
|
|
try page.setFont(.helvetica, 10);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(100, 520, "Cubic Bezier: S-curve");
|
|
|
|
// Draw control points and lines for visualization
|
|
try page.setLineWidth(0.5);
|
|
page.setStrokeColor(pdf.Color.light_gray);
|
|
try page.drawLine(100, 650, 150, 700);
|
|
try page.drawLine(250, 550, 300, 600);
|
|
|
|
// Control point markers
|
|
page.setFillColor(pdf.Color.rgb(100, 100, 255));
|
|
try page.fillCircle(100, 650, 4);
|
|
try page.fillCircle(150, 700, 4);
|
|
try page.fillCircle(250, 550, 4);
|
|
try page.fillCircle(300, 600, 4);
|
|
|
|
// Quadratic Bezier curve
|
|
try page.setLineWidth(2);
|
|
page.setStrokeColor(pdf.Color.rgb(50, 205, 50)); // Lime green
|
|
|
|
try page.drawQuadBezier(
|
|
350, 650, // Start point
|
|
425, 550, // Control point
|
|
500, 650, // End point
|
|
);
|
|
|
|
// Label
|
|
try page.setFont(.helvetica, 10);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(350, 520, "Quadratic Bezier: Parabola");
|
|
|
|
// Control point visualization
|
|
try page.setLineWidth(0.5);
|
|
page.setStrokeColor(pdf.Color.light_gray);
|
|
try page.drawLine(350, 650, 425, 550);
|
|
try page.drawLine(425, 550, 500, 650);
|
|
|
|
page.setFillColor(pdf.Color.rgb(100, 100, 255));
|
|
try page.fillCircle(350, 650, 4);
|
|
try page.fillCircle(425, 550, 4);
|
|
try page.fillCircle(500, 650, 4);
|
|
|
|
// Multiple connected curves
|
|
try page.setLineWidth(3);
|
|
page.setStrokeColor(pdf.Color.rgb(255, 140, 0)); // Dark orange
|
|
|
|
// First curve
|
|
try page.drawBezier(50, 400, 100, 450, 150, 350, 200, 400);
|
|
// Second curve (connected)
|
|
try page.drawBezier(200, 400, 250, 450, 300, 350, 350, 400);
|
|
// Third curve (connected)
|
|
try page.drawBezier(350, 400, 400, 450, 450, 350, 500, 400);
|
|
|
|
try page.setFont(.helvetica, 10);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(150, 320, "Connected Bezier curves for smooth paths");
|
|
|
|
// Footer
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.medium_gray);
|
|
try page.drawText(250, 50, "Page 1 of 2 - zpdf Curves Demo");
|
|
}
|
|
|
|
// =========================================================================
|
|
// Page 2: Circles, Ellipses, and Arcs
|
|
// =========================================================================
|
|
{
|
|
const page = try doc.addPage(.{});
|
|
|
|
// Title
|
|
try page.setFont(.helvetica_bold, 24);
|
|
page.setFillColor(pdf.Color.rgb(41, 98, 255));
|
|
try page.drawText(50, 780, "Circles, Ellipses & Arcs");
|
|
|
|
try page.setFont(.helvetica, 11);
|
|
page.setFillColor(pdf.Color.black);
|
|
try page.drawText(50, 755, "Smooth curves approximated with cubic Bezier segments");
|
|
|
|
// Circles
|
|
try page.setFont(.helvetica_bold, 14);
|
|
page.setFillColor(pdf.Color.black);
|
|
try page.drawText(50, 700, "Circles");
|
|
|
|
try page.setLineWidth(2);
|
|
|
|
// Stroke circle
|
|
page.setStrokeColor(pdf.Color.rgb(0, 128, 0));
|
|
try page.drawCircle(120, 620, 40);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(90, 565, "Stroked");
|
|
|
|
// Filled circle
|
|
page.setFillColor(pdf.Color.rgb(135, 206, 250)); // Light sky blue
|
|
try page.fillCircle(220, 620, 40);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(195, 565, "Filled");
|
|
|
|
// Fill + stroke circle
|
|
page.setFillColor(pdf.Color.rgb(255, 218, 185)); // Peach
|
|
page.setStrokeColor(pdf.Color.rgb(205, 92, 92)); // Indian red
|
|
try page.circle(320, 620, 40, .fill_stroke);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(290, 565, "Fill+Stroke");
|
|
|
|
// Nested circles
|
|
page.setStrokeColor(pdf.Color.rgb(128, 0, 128));
|
|
try page.setLineWidth(1);
|
|
try page.drawCircle(440, 620, 45);
|
|
try page.drawCircle(440, 620, 35);
|
|
try page.drawCircle(440, 620, 25);
|
|
try page.drawCircle(440, 620, 15);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(415, 565, "Nested");
|
|
|
|
// Ellipses
|
|
try page.setFont(.helvetica_bold, 14);
|
|
page.setFillColor(pdf.Color.black);
|
|
try page.drawText(50, 520, "Ellipses");
|
|
|
|
try page.setLineWidth(2);
|
|
|
|
// Horizontal ellipse
|
|
page.setStrokeColor(pdf.Color.rgb(255, 69, 0)); // Orange red
|
|
try page.drawEllipse(120, 450, 60, 30);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(85, 405, "Horizontal");
|
|
|
|
// Vertical ellipse
|
|
page.setFillColor(pdf.Color.rgb(147, 112, 219)); // Medium purple
|
|
try page.fillEllipse(250, 450, 30, 50);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(225, 385, "Vertical");
|
|
|
|
// Ellipse with stroke
|
|
page.setFillColor(pdf.Color.rgb(255, 255, 224)); // Light yellow
|
|
page.setStrokeColor(pdf.Color.rgb(184, 134, 11)); // Dark goldenrod
|
|
try page.ellipse(380, 450, 70, 35, .fill_stroke);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(345, 400, "Fill+Stroke");
|
|
|
|
// Arcs
|
|
try page.setFont(.helvetica_bold, 14);
|
|
page.setFillColor(pdf.Color.black);
|
|
try page.drawText(50, 340, "Arcs");
|
|
|
|
try page.setLineWidth(3);
|
|
|
|
// Quarter circle arc (0 to 90 degrees)
|
|
page.setStrokeColor(pdf.Color.rgb(30, 144, 255)); // Dodger blue
|
|
try page.drawArc(120, 250, 50, 50, 0, 90);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(90, 185, "90 degrees");
|
|
|
|
// Half circle arc (0 to 180 degrees)
|
|
page.setStrokeColor(pdf.Color.rgb(50, 205, 50)); // Lime green
|
|
try page.drawArc(250, 250, 50, 50, 0, 180);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(215, 185, "180 degrees");
|
|
|
|
// Three-quarter arc
|
|
page.setStrokeColor(pdf.Color.rgb(255, 165, 0)); // Orange
|
|
try page.drawArc(380, 250, 50, 50, 45, 315);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(345, 185, "270 degrees");
|
|
|
|
// Elliptical arc
|
|
page.setStrokeColor(pdf.Color.rgb(220, 20, 60)); // Crimson
|
|
try page.drawArc(500, 250, 40, 60, 30, 270);
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.dark_gray);
|
|
try page.drawText(465, 175, "Elliptical arc");
|
|
|
|
// Footer
|
|
try page.setFont(.helvetica, 9);
|
|
page.setFillColor(pdf.Color.medium_gray);
|
|
try page.drawText(250, 50, "Page 2 of 2 - zpdf Curves Demo");
|
|
}
|
|
|
|
// Save
|
|
const filename = "curves_demo.pdf";
|
|
try doc.save(filename);
|
|
|
|
std.debug.print("Created: {s} ({d} pages)\n", .{ filename, doc.pageCount() });
|
|
std.debug.print("Done!\n", .{});
|
|
}
|