zcatpdf/examples/links_demo.zig
reugenio f09922076f refactor: Rename zpdf to zcatpdf for consistency with zcat* family
- Renamed all references from zpdf to zcatpdf
- Module import: @import("zcatpdf")
- Consistent with zcatui, zcatgui naming convention
- All lowercase per Zig standards

Note: Directory rename (zpdf -> zcatpdf) and Forgejo repo rename
should be done manually after this commit.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 02:10:57 +01:00

177 lines
6.6 KiB
Zig

//! Links Demo - Demonstrates clickable URL links in PDFs
//!
//! Shows how to create:
//! - Clickable URL links (external websites)
//! - Internal page links (jump to page)
//! - Visual link styling (blue underlined text)
const std = @import("std");
const pdf = @import("zcatpdf");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
std.debug.print("zcatpdf - Links Demo\n", .{});
var doc = pdf.Pdf.init(allocator, .{});
defer doc.deinit();
doc.setTitle("Links Demo");
doc.setAuthor("zcatpdf");
// =========================================================================
// Page 1: External URL Links
// =========================================================================
var page1 = try doc.addPage(.{});
page1.setMargins(50, 50, 50);
// Title
try page1.setFont(.helvetica_bold, 24);
page1.setFillColor(pdf.Color.rgb(41, 98, 255));
page1.setXY(50, 780);
try page1.cell(0, 30, "Clickable Links Demo", pdf.Border.none, .center, false);
page1.ln(50);
// Description
try page1.setFont(.helvetica, 12);
page1.setFillColor(pdf.Color.black);
const desc =
\\This PDF demonstrates clickable links. When you view this in a PDF reader,
\\you can click on the blue underlined text to open URLs in your browser.
;
try page1.multiCell(500, null, desc, pdf.Border.none, .left, false);
page1.ln(30);
// Section: External Links
try page1.setFont(.helvetica_bold, 16);
page1.setFillColor(pdf.Color.rgb(51, 51, 51));
try page1.cell(0, 25, "External URL Links", pdf.Border.none, .left, false);
page1.ln(30);
try page1.setFont(.helvetica, 12);
page1.setFillColor(pdf.Color.black);
// Link 1: Example website
try page1.cell(0, 18, "Visit the example website: ", pdf.Border.none, .left, false);
_ = try page1.writeUrlLink("https://example.com", "https://example.com");
page1.ln(25);
// Link 2: GitHub
try page1.cell(0, 18, "Check out Zig on GitHub: ", pdf.Border.none, .left, false);
_ = try page1.writeUrlLink("Zig Language", "https://github.com/ziglang/zig");
page1.ln(25);
// Link 3: Email
try page1.cell(0, 18, "Send us an email: ", pdf.Border.none, .left, false);
_ = try page1.writeUrlLink("contact@example.com", "mailto:contact@example.com");
page1.ln(40);
// Section: Internal Links
try page1.setFont(.helvetica_bold, 16);
page1.setFillColor(pdf.Color.rgb(51, 51, 51));
try page1.cell(0, 25, "Internal Page Links", pdf.Border.none, .left, false);
page1.ln(30);
try page1.setFont(.helvetica, 12);
page1.setFillColor(pdf.Color.black);
try page1.cell(0, 18, "Click to jump to: ", pdf.Border.none, .left, false);
// Internal link to page 2
const link_text = "Page 2 - More Information";
const link_width = try page1.drawLink(page1.getX(), page1.getY(), link_text);
try page1.addInternalLink(1, page1.getX(), page1.getY() - 2, link_width, 16);
page1.ln(40);
// Information box
page1.setFillColor(pdf.Color.rgb(240, 248, 255));
try page1.fillRect(50, page1.getY() - 80, 495, 80);
try page1.setFont(.helvetica, 11);
page1.setFillColor(pdf.Color.rgb(51, 51, 51));
page1.setXY(60, page1.getY() - 15);
const info_text =
\\Note: Link clickability depends on your PDF viewer. Most modern viewers
\\(Adobe Reader, Preview, Chrome, Firefox) support clickable links.
\\The blue underlined styling is visual, while the annotation makes it clickable.
;
try page1.multiCell(475, null, info_text, pdf.Border.none, .left, false);
// =========================================================================
// Page 2: More Information
// =========================================================================
var page2 = try doc.addPage(.{});
page2.setMargins(50, 50, 50);
// Title
try page2.setFont(.helvetica_bold, 24);
page2.setFillColor(pdf.Color.rgb(41, 98, 255));
page2.setXY(50, 780);
try page2.cell(0, 30, "Page 2 - More Information", pdf.Border.none, .center, false);
page2.ln(50);
try page2.setFont(.helvetica, 12);
page2.setFillColor(pdf.Color.black);
const page2_text =
\\You navigated here from a clickable internal link!
\\
\\Internal links allow you to create table of contents, cross-references,
\\and navigation within your PDF documents.
\\
\\The link annotation stores the target page number and the PDF viewer
\\handles the navigation when clicked.
;
try page2.multiCell(500, null, page2_text, pdf.Border.none, .left, false);
page2.ln(30);
// Link back to page 1
try page2.cell(0, 18, "Go back to: ", pdf.Border.none, .left, false);
const back_text = "Page 1 - Links Demo";
const back_width = try page2.drawLink(page2.getX(), page2.getY(), back_text);
try page2.addInternalLink(0, page2.getX(), page2.getY() - 2, back_width, 16);
page2.ln(50);
// Technical details
try page2.setFont(.helvetica_bold, 14);
page2.setFillColor(pdf.Color.rgb(51, 51, 51));
try page2.cell(0, 20, "How Links Work in PDF", pdf.Border.none, .left, false);
page2.ln(25);
try page2.setFont(.helvetica, 11);
page2.setFillColor(pdf.Color.black);
const tech_text =
\\PDF links are implemented using Annotation objects (/Type /Annot /Subtype /Link).
\\
\\Each link annotation contains:
\\- /Rect: The clickable area coordinates [x1, y1, x2, y2]
\\- /A: Action dictionary for URL links (/S /URI /URI "url")
\\- /Dest: Destination for internal links (page reference)
\\- /Border: Border style (we use [0 0 0] for invisible borders)
\\
\\The visual styling (blue text + underline) is separate from the annotation.
\\zcatpdf's urlLink() and writeUrlLink() methods combine both automatically.
;
try page2.multiCell(500, null, tech_text, pdf.Border.none, .left, false);
// Add page numbers
try pdf.Pagination.addPageNumbers(&doc, .{
.format = "Page {PAGE} of {PAGES}",
.position = .bottom_center,
});
// Footer
try pdf.Pagination.addFooter(&doc, "Generated with zcatpdf - Links Demo", .{
.alignment = .center,
.font_size = 8,
.color = pdf.Color.light_gray,
});
// Save
const filename = "links_demo.pdf";
try doc.save(filename);
std.debug.print("Created: {s}\n", .{filename});
std.debug.print("Open in a PDF viewer and click the links!\n", .{});
std.debug.print("Done!\n", .{});
}