Skip to content

feat(drawing): add transparency groups, soft masks, and gradient stop opacity#39

Open
Mythie wants to merge 1 commit intomainfrom
feat/soft-mask-gradients
Open

feat(drawing): add transparency groups, soft masks, and gradient stop opacity#39
Mythie wants to merge 1 commit intomainfrom
feat/soft-mask-gradients

Conversation

@Mythie
Copy link
Contributor

@Mythie Mythie commented Feb 28, 2026

Implement PDF 1.4+ transparency primitives:

  • Form XObject transparency group support (isolated/knockout/colorSpace)
  • ExtGState soft mask authoring (Luminosity, Alpha, None reset)
  • ColorStop.opacity on gradient APIs with automatic soft-mask composition
  • Draw-time opacity routing: opaque/uniform/varying fast paths
  • Composable graphics state: soft mask + blend mode + constant opacity

Includes comprehensive visual integration tests and structural validation.

image

… opacity

Implement PDF 1.4+ transparency primitives:
- Form XObject transparency group support (isolated/knockout/colorSpace)
- ExtGState soft mask authoring (Luminosity, Alpha, None reset)
- ColorStop.opacity on gradient APIs with automatic soft-mask composition
- Draw-time opacity routing: opaque/uniform/varying fast paths
- Composable graphics state: soft mask + blend mode + constant opacity

Includes comprehensive visual integration tests and structural validation.
@vercel
Copy link
Contributor

vercel bot commented Feb 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
core Ready Ready Preview, Comment Feb 28, 2026 9:54am

@github-actions
Copy link
Contributor

Benchmark Results

Comparison

Load PDF

Benchmark Mean p99 RME Samples
libpdf 2.49ms 4.17ms ±1.7% 201
pdf-lib 38.41ms 42.51ms ±3.4% 14

Create blank PDF

Benchmark Mean p99 RME Samples
libpdf 61μs 132μs ±1.6% 8228
pdf-lib 407μs 1.53ms ±2.4% 1228

Add 10 pages

Benchmark Mean p99 RME Samples
libpdf 102μs 161μs ±1.2% 4896
pdf-lib 514μs 1.91ms ±2.8% 974

Draw 50 rectangles

Benchmark Mean p99 RME Samples
libpdf 185μs 449μs ±0.9% 2698
pdf-lib 1.66ms 5.84ms ±6.2% 302

Load and save PDF

Benchmark Mean p99 RME Samples
libpdf 2.51ms 3.26ms ±1.4% 200
pdf-lib 87.48ms 94.26ms ±3.5% 10

Load, modify, and save PDF

Benchmark Mean p99 RME Samples
libpdf 45.50ms 59.14ms ±10.5% 11
pdf-lib 89.15ms 101.24ms ±5.8% 10

Extract single page from 100-page PDF

Benchmark Mean p99 RME Samples
libpdf 3.72ms 6.48ms ±2.1% 135
pdf-lib 9.03ms 11.51ms ±1.7% 56

Split 100-page PDF into single-page PDFs

Benchmark Mean p99 RME Samples
libpdf 32.86ms 34.56ms ±1.2% 16
pdf-lib 86.85ms 92.29ms ±3.8% 6

Split 2000-page PDF into single-page PDFs (0.9MB)

Benchmark Mean p99 RME Samples
libpdf 623.64ms 623.64ms ±0.0% 1
pdf-lib 1.62s 1.62s ±0.0% 1

Copy 10 pages between documents

Benchmark Mean p99 RME Samples
libpdf 4.52ms 5.19ms ±1.0% 111
pdf-lib 11.79ms 12.78ms ±1.2% 43

Merge 2 x 100-page PDFs

Benchmark Mean p99 RME Samples
libpdf 14.03ms 16.18ms ±1.4% 36
pdf-lib 55.15ms 61.88ms ±3.4% 10
Copying

Copy pages between documents

Benchmark Mean p99 RME Samples
copy 1 page 1.07ms 2.37ms ±4.8% 469
copy 10 pages from 100-page PDF 4.53ms 6.58ms ±2.0% 111
copy all 100 pages 7.29ms 8.05ms ±1.0% 69

Duplicate pages within same document

Benchmark Mean p99 RME Samples
duplicate page 0 892μs 1.61ms ±1.2% 561
duplicate all pages (double the document) 880μs 1.61ms ±1.1% 569

Merge PDFs

Benchmark Mean p99 RME Samples
merge 2 small PDFs 1.43ms 1.93ms ±0.7% 350
merge 10 small PDFs 7.53ms 8.54ms ±1.0% 67
merge 2 x 100-page PDFs 13.52ms 15.36ms ±1.2% 37
Drawing

benchmarks/drawing.bench.ts

Benchmark Mean p99 RME Samples
draw 100 rectangles 311μs 688μs ±2.2% 1608
draw 100 circles 263μs 538μs ±0.8% 1903
draw 100 lines 487μs 1.08ms ±1.4% 1027
draw 100 text lines (standard font) 1.54ms 2.32ms ±1.2% 325
create 10 pages with mixed content 1.19ms 2.11ms ±1.7% 422
Forms

benchmarks/forms.bench.ts

Benchmark Mean p99 RME Samples
get form fields 3.28ms 5.79ms ±3.2% 153
fill text fields 11.22ms 16.03ms ±4.0% 45
read field values 3.01ms 5.25ms ±2.1% 166
flatten form 8.34ms 11.37ms ±2.6% 60
Loading

benchmarks/loading.bench.ts

Benchmark Mean p99 RME Samples
load small PDF (888B) 61μs 158μs ±0.9% 8227
load medium PDF (19KB) 96μs 200μs ±0.7% 5195
load form PDF (116KB) 1.35ms 2.61ms ±2.2% 370
load heavy PDF (9.9MB) 2.35ms 2.84ms ±0.7% 213
Saving

benchmarks/saving.bench.ts

Benchmark Mean p99 RME Samples
save unmodified (19KB) 109μs 267μs ±1.0% 4585
save with modifications (19KB) 717μs 1.35ms ±1.2% 699
incremental save (19KB) 154μs 327μs ±1.0% 3246
save heavy PDF (9.9MB) 2.38ms 2.74ms ±0.5% 211
incremental save heavy PDF (9.9MB) 8.51ms 9.92ms ±2.8% 59
Splitting

Extract single page

Benchmark Mean p99 RME Samples
extractPages (1 page from small PDF) 973μs 1.93ms ±2.5% 514
extractPages (1 page from 100-page PDF) 3.61ms 6.55ms ±2.3% 139
extractPages (1 page from 2000-page PDF) 57.11ms 58.13ms ±0.6% 10

Split into single-page PDFs

Benchmark Mean p99 RME Samples
split 100-page PDF (0.1MB) 30.84ms 35.74ms ±3.5% 17
split 2000-page PDF (0.9MB) 572.88ms 572.88ms ±0.0% 1

Batch page extraction

Benchmark Mean p99 RME Samples
extract first 10 pages from 2000-page PDF 58.05ms 59.48ms ±1.1% 9
extract first 100 pages from 2000-page PDF 62.20ms 65.72ms ±2.4% 9
extract every 10th page from 2000-page PDF (200 pages) 69.31ms 80.33ms ±5.7% 8
Environment
  • Runner: Linux (X64)
  • Runtime: Bun 1.3.10

Results are machine-dependent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant