Skip to content

feat(forms): support CID fonts in form field appearances#47

Merged
Mythie merged 3 commits intomainfrom
feat/form-cid-font-support
Mar 11, 2026
Merged

feat(forms): support CID fonts in form field appearances#47
Mythie merged 3 commits intomainfrom
feat/form-cid-font-support

Conversation

@Mythie
Copy link
Contributor

@Mythie Mythie commented Mar 10, 2026

CID-keyed fonts (Type0 with Identity-H/V encoding) can now be used
for form field appearance generation. This enables correct rendering
of CJK and Unicode text in existing PDF form fonts.

Key changes:

  • CIDFont: add Unicode→charcode mapping, glyph renderability checks,
    and ToUnicode reverse lookup for accurate encoding
  • FontProgram: add hasRenderableGlyph() and getGlyphIdForUnicode()
    across all font program types (TrueType, CFF, CFF-CID, Type1)
  • ExistingFont: full CID font encoding support with canUseForAppearance
    validation and 2-byte character code generation
  • Deduplicate ~500 lines of shared helpers from button/text/choice
    appearance generators into appearance-utils.ts
  • Consolidate duplicate Standard 14 alias tables into single source

CID-keyed fonts (Type0 with Identity-H/V encoding) can now be used
for form field appearance generation. This enables correct rendering
of CJK and Unicode text in existing PDF form fonts.

Key changes:
- CIDFont: add Unicode→charcode mapping, glyph renderability checks,
  and ToUnicode reverse lookup for accurate encoding
- FontProgram: add hasRenderableGlyph() and getGlyphIdForUnicode()
  across all font program types (TrueType, CFF, CFF-CID, Type1)
- ExistingFont: full CID font encoding support with canUseForAppearance
  validation and 2-byte character code generation
- Deduplicate ~500 lines of shared helpers from button/text/choice
  appearance generators into appearance-utils.ts
- Consolidate duplicate Standard 14 alias tables into single source
@vercel
Copy link
Contributor

vercel bot commented Mar 10, 2026

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

Project Deployment Actions Updated (UTC)
core Ready Ready Preview, Comment Mar 11, 2026 2:22am

@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

Benchmark Results

Comparison

Load PDF

Benchmark Mean p99 RME Samples
libpdf 2.40ms 3.15ms ±1.2% 209
pdf-lib 38.75ms 43.52ms ±4.5% 13

Create blank PDF

Benchmark Mean p99 RME Samples
libpdf 44μs 87μs ±1.7% 11363
pdf-lib 348μs 1.43ms ±2.7% 1439

Add 10 pages

Benchmark Mean p99 RME Samples
libpdf 81μs 152μs ±1.1% 6155
pdf-lib 436μs 1.73ms ±2.8% 1148

Draw 50 rectangles

Benchmark Mean p99 RME Samples
libpdf 292μs 755μs ±1.3% 1712
pdf-lib 1.59ms 6.71ms ±7.2% 315

Load and save PDF

Benchmark Mean p99 RME Samples
libpdf 2.52ms 4.50ms ±2.2% 199
pdf-lib 92.33ms 103.69ms ±6.0% 10

Load, modify, and save PDF

Benchmark Mean p99 RME Samples
libpdf 40.71ms 50.08ms ±6.0% 13
pdf-lib 83.86ms 89.29ms ±2.5% 10

Extract single page from 100-page PDF

Benchmark Mean p99 RME Samples
libpdf 3.48ms 4.00ms ±1.2% 144
pdf-lib 8.98ms 10.86ms ±1.5% 56

Split 100-page PDF into single-page PDFs

Benchmark Mean p99 RME Samples
libpdf 29.71ms 35.65ms ±2.8% 17
pdf-lib 83.15ms 90.87ms ±4.9% 7

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

Benchmark Mean p99 RME Samples
libpdf 552.84ms 552.84ms ±0.0% 1
pdf-lib 1.50s 1.50s ±0.0% 1

Copy 10 pages between documents

Benchmark Mean p99 RME Samples
libpdf 4.33ms 5.04ms ±1.0% 116
pdf-lib 11.63ms 12.67ms ±1.0% 43

Merge 2 x 100-page PDFs

Benchmark Mean p99 RME Samples
libpdf 13.53ms 14.23ms ±0.8% 37
pdf-lib 54.12ms 55.78ms ±1.8% 10
Copying

Copy pages between documents

Benchmark Mean p99 RME Samples
copy 1 page 937μs 2.18ms ±2.9% 534
copy 10 pages from 100-page PDF 4.17ms 6.26ms ±1.9% 120
copy all 100 pages 6.89ms 7.91ms ±0.9% 73

Duplicate pages within same document

Benchmark Mean p99 RME Samples
duplicate page 0 794μs 1.45ms ±1.1% 630
duplicate all pages (double the document) 799μs 1.47ms ±1.2% 627

Merge PDFs

Benchmark Mean p99 RME Samples
merge 2 small PDFs 1.36ms 2.32ms ±1.8% 368
merge 10 small PDFs 7.10ms 10.10ms ±1.8% 71
merge 2 x 100-page PDFs 12.62ms 13.19ms ±0.7% 40
Drawing

benchmarks/drawing.bench.ts

Benchmark Mean p99 RME Samples
draw 100 rectangles 544μs 1.33ms ±2.4% 920
draw 100 circles 1.22ms 2.81ms ±2.8% 412
draw 100 lines 474μs 1.15ms ±1.4% 1055
draw 100 text lines (standard font) 1.53ms 2.29ms ±1.3% 327
create 10 pages with mixed content 1.27ms 2.11ms ±1.6% 394
Forms

benchmarks/forms.bench.ts

Benchmark Mean p99 RME Samples
get form fields 3.02ms 6.28ms ±3.9% 166
fill text fields 10.90ms 15.93ms ±5.0% 46
read field values 2.74ms 4.99ms ±2.0% 183
flatten form 7.78ms 10.70ms ±2.6% 65
Loading

benchmarks/loading.bench.ts

Benchmark Mean p99 RME Samples
load small PDF (888B) 54μs 122μs ±0.7% 9324
load medium PDF (19KB) 85μs 113μs ±0.5% 5887
load form PDF (116KB) 1.44ms 2.60ms ±1.7% 348
load heavy PDF (9.9MB) 2.25ms 2.92ms ±1.1% 223
Saving

benchmarks/saving.bench.ts

Benchmark Mean p99 RME Samples
save unmodified (19KB) 93μs 192μs ±0.7% 5390
save with modifications (19KB) 665μs 1.25ms ±1.5% 752
incremental save (19KB) 133μs 296μs ±0.9% 3769
save heavy PDF (9.9MB) 2.20ms 2.61ms ±0.6% 227
incremental save heavy PDF (9.9MB) 9.01ms 15.08ms ±6.6% 56
Splitting

Extract single page

Benchmark Mean p99 RME Samples
extractPages (1 page from small PDF) 931μs 2.34ms ±3.2% 538
extractPages (1 page from 100-page PDF) 3.34ms 5.78ms ±1.6% 150
extractPages (1 page from 2000-page PDF) 52.89ms 54.04ms ±0.7% 10

Split into single-page PDFs

Benchmark Mean p99 RME Samples
split 100-page PDF (0.1MB) 28.03ms 32.14ms ±3.4% 18
split 2000-page PDF (0.9MB) 529.98ms 529.98ms ±0.0% 1

Batch page extraction

Benchmark Mean p99 RME Samples
extract first 10 pages from 2000-page PDF 55.66ms 60.52ms ±2.8% 9
extract first 100 pages from 2000-page PDF 58.13ms 60.04ms ±1.5% 9
extract every 10th page from 2000-page PDF (200 pages) 63.06ms 74.14ms ±6.0% 8
Environment
  • Runner: Linux (X64)
  • Runtime: Bun 1.3.10

Results are machine-dependent.

@Mythie Mythie merged commit 48c044e into main Mar 11, 2026
6 checks passed
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