Tincture - Typographic PDF generation with no runtime dependencies

Pure Elixir PDF generation. No Chrome, no wkhtmltopdf, no NIFs, no ports. Font parsing, subsetting, hyphenation, line breaking, serialisation, encryption and signing are all Elixir/OTP.

Fork of ex_guten (Hugh Watkins, MIT), itself a port of Joe Armstrong’s erlguten. Most of the engine — TrueType/OpenType parser, Knuth-Plass line breaker, TeX hyphenation, PDF serialiser — is Hugh’s work. Git history preserved, copyright retained in LICENSE, full chain in NOTICE.

Tincture.new()
|> Tincture.page_size(:a4)
|> Tincture.register_ttf_font("Body", "Georgia.ttf")
|> Tincture.set_font("Body", 11)
|> Tincture.text_paragraph(50, 700, rich_text, 495,
     align: :justified, line_break: :optimal)
|> Tincture.export()

Features

  • Typography — TeX hyphenation (Liang patterns, 5 locales), Knuth-Plass global line breaking, configurable widow/orphan/hyphen penalties, GPOS kerning, GSUB ligatures
  • Fonts — standard 14; TrueType/OpenType embedding, subsetting on by default (70–90% reduction)
  • Layout — text boxes with spill, multi-column flow, tables with auto column widths, page templates with headers/footers/numbering, XML-driven documents
  • Graphics — lines, rects, circles, Bézier paths, fill/stroke/clip; JPEG and PNG with alpha
  • Documents — metadata, bookmarks, links, forms (text, choice, checkbox, radio group, push button, signature), AES-256 encryption
  • Standards — tagged PDF (PDF/UA), PDF/A with built-in sRGB output intent, detached PKCS#7 signatures
  • Telemetry — spans per document, page and embedded font; :telemetry is an optional dep

Conformance

Checked with veraPDF 1.30.2 and OpenSSL 3.6, not asserted:

Standard Result
PDF/UA-1 (ISO 14289-1) isCompliant=true, 106/106 rules
PDF/A-2b (ISO 19005-2) isCompliant=true, 144/144 rules
PDF/A-2u isCompliant=true, 146/146 rules
PDF/A-2a isCompliant=true, 153/153 rules
PKCS#7 detached verified by openssl cms -verify

Example documents are committed. Reproduce:

verapdf --flavour ua1 examples/output/compliant.pdf
verapdf --flavour 2a  examples/output/archival.pdf

set_pdf_a/2 writes a conformance claim into the file, so export/2 refuses to emit a document that breaks the rules it can check, listing each violation and clause. enforce: false overrides.

Install

{:tincture, "~> 0.1"}

0.x is deliberate — the API under this name is new and may move before 1.0.

1,225 tests, 89% coverage, Credo --strict clean, Dialyzer clean, CI on Elixir 1.16–1.19. Seven examples with output PDFs committed.

Hex: tincture | Hex
Docs: Tincture v0.1.0 — Documentation
Roadmap: tincture/ROADMAP.md at main · thatsme/tincture · GitHub
Examples: tincture/examples at main · thatsme/tincture · GitHub

33 Likes