zcatpdf/examples/transparency_demo.zig
reugenio 3826cbaed4 Release v1.0 - Feature Complete PDF Generation Library
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>
2025-12-09 02:01:17 +01:00

209 lines
7 KiB
Zig

//! Transparency Demo - Alpha/Opacity Support
//!
//! Demonstrates the transparency capabilities of zpdf including:
//! - Fill opacity for shapes and text
//! - Stroke opacity for lines and outlines
//! - Layered transparent objects
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 - Transparency Demo\n", .{});
var doc = pdf.Pdf.init(allocator, .{});
defer doc.deinit();
doc.setTitle("Transparency Demo");
doc.setAuthor("zpdf");
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, "Transparency / Alpha");
try page.setFont(.helvetica, 11);
page.setFillColor(pdf.Color.black);
try page.drawText(50, 755, "Demonstrating fill and stroke opacity using ExtGState");
// =========================================================================
// Fill Opacity Examples
// =========================================================================
try page.setFont(.helvetica_bold, 14);
page.setFillColor(pdf.Color.black);
try page.drawText(50, 710, "Fill Opacity:");
// Draw overlapping squares with different opacities
const base_x: f32 = 80;
const base_y: f32 = 550;
const size: f32 = 100;
// First layer - red square (fully opaque)
page.setFillColor(pdf.Color.rgb(255, 0, 0));
try page.fillRect(base_x, base_y, size, size);
// Second layer - green square (75% opacity)
page.setFillColor(pdf.Color.rgb(0, 255, 0));
try page.setFillOpacity(0.75);
try page.fillRect(base_x + 40, base_y + 30, size, size);
// Third layer - blue square (50% opacity)
page.setFillColor(pdf.Color.rgb(0, 0, 255));
try page.setFillOpacity(0.5);
try page.fillRect(base_x + 80, base_y + 60, size, size);
// Labels
try page.setOpacity(1.0); // Reset to fully opaque
try page.setFont(.helvetica, 9);
page.setFillColor(pdf.Color.dark_gray);
try page.drawText(base_x, base_y - 15, "Overlapping (100%, 75%, 50%)");
// Individual opacity examples
const opacities = [_]f32{ 1.0, 0.75, 0.5, 0.25, 0.1 };
var x: f32 = 280;
for (opacities) |opacity| {
try page.setFillOpacity(opacity);
page.setFillColor(pdf.Color.rgb(128, 0, 128)); // Purple
try page.fillRect(x, base_y + 30, 60, 60);
try page.setOpacity(1.0); // Reset for label
try page.setFont(.helvetica, 9);
page.setFillColor(pdf.Color.dark_gray);
var buf: [32]u8 = undefined;
const label = std.fmt.bufPrint(&buf, "{d}%", .{@as(u32, @intFromFloat(opacity * 100))}) catch "??";
try page.drawText(x + 20, base_y + 10, label);
x += 70;
}
// =========================================================================
// Stroke Opacity Examples
// =========================================================================
try page.setOpacity(1.0);
try page.setFont(.helvetica_bold, 14);
page.setFillColor(pdf.Color.black);
try page.drawText(50, 500, "Stroke Opacity:");
try page.setLineWidth(8);
page.setStrokeColor(pdf.Color.rgb(220, 20, 60)); // Crimson
x = 80;
for (opacities) |opacity| {
try page.setStrokeOpacity(opacity);
try page.drawLine(x, 420, x + 80, 420);
try page.setOpacity(1.0);
try page.setFont(.helvetica, 9);
page.setFillColor(pdf.Color.dark_gray);
var buf: [32]u8 = undefined;
const label = std.fmt.bufPrint(&buf, "{d}%", .{@as(u32, @intFromFloat(opacity * 100))}) catch "??";
try page.drawText(x + 20, 400, label);
x += 100;
}
// =========================================================================
// Combined Fill and Stroke Opacity
// =========================================================================
try page.setOpacity(1.0);
try page.setFont(.helvetica_bold, 14);
page.setFillColor(pdf.Color.black);
try page.drawText(50, 370, "Combined Fill + Stroke Opacity:");
try page.setLineWidth(4);
x = 80;
const fill_opacities = [_]f32{ 1.0, 0.5, 0.25 };
const stroke_opacities = [_]f32{ 1.0, 0.5, 0.25 };
for (fill_opacities, stroke_opacities) |fill_op, stroke_op| {
page.setFillColor(pdf.Color.rgb(100, 149, 237)); // Cornflower blue
page.setStrokeColor(pdf.Color.rgb(0, 0, 139)); // Dark blue
try page.setFillOpacity(fill_op);
try page.setStrokeOpacity(stroke_op);
try page.drawFilledRect(x, 280, 80, 60);
try page.setOpacity(1.0);
try page.setFont(.helvetica, 8);
page.setFillColor(pdf.Color.dark_gray);
var buf: [32]u8 = undefined;
const label = std.fmt.bufPrint(&buf, "f:{d}% s:{d}%", .{
@as(u32, @intFromFloat(fill_op * 100)),
@as(u32, @intFromFloat(stroke_op * 100)),
}) catch "??";
try page.drawText(x, 265, label);
x += 120;
}
// =========================================================================
// Transparent Text
// =========================================================================
try page.setOpacity(1.0);
try page.setFont(.helvetica_bold, 14);
page.setFillColor(pdf.Color.black);
try page.drawText(50, 230, "Transparent Text:");
// Background rectangle
page.setFillColor(pdf.Color.rgb(255, 215, 0)); // Gold
try page.fillRect(80, 130, 450, 70);
// Overlapping text with different opacities
try page.setFont(.helvetica_bold, 48);
page.setFillColor(pdf.Color.rgb(255, 0, 0));
try page.setFillOpacity(1.0);
try page.drawText(100, 150, "ZPDF");
page.setFillColor(pdf.Color.rgb(0, 128, 0));
try page.setFillOpacity(0.6);
try page.drawText(150, 160, "ZPDF");
page.setFillColor(pdf.Color.rgb(0, 0, 255));
try page.setFillOpacity(0.3);
try page.drawText(200, 170, "ZPDF");
// =========================================================================
// Transparent Circles (Venn diagram style)
// =========================================================================
try page.setOpacity(1.0);
try page.setFont(.helvetica_bold, 14);
page.setFillColor(pdf.Color.black);
try page.drawText(350, 230, "Overlapping Circles:");
try page.setFillOpacity(0.5);
page.setFillColor(pdf.Color.rgb(255, 0, 0));
try page.fillCircle(420, 170, 50);
page.setFillColor(pdf.Color.rgb(0, 255, 0));
try page.fillCircle(460, 170, 50);
page.setFillColor(pdf.Color.rgb(0, 0, 255));
try page.fillCircle(440, 130, 50);
// Footer
try page.setOpacity(1.0);
try page.setFont(.helvetica, 9);
page.setFillColor(pdf.Color.medium_gray);
try page.drawText(250, 50, "zpdf Transparency Demo");
// Save
const filename = "transparency_demo.pdf";
try doc.save(filename);
std.debug.print("Created: {s} ({d} pages)\n", .{ filename, doc.pageCount() });
std.debug.print("Done!\n", .{});
}