Packages
A pure Elixir PDF generation engine with multi-page documents, text layout, vector graphics, standard PDF fonts, embedded TrueType fonts, Unicode visible text, JPEG and PNG images, transparency, compression, page margins, coordinate systems, and metadata.
Current section
Files
Jump to
Current section
Files
paper_forge
CHANGELOG.md
CHANGELOG.md
# Changelog
All notable changes to PaperForge will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.0] - 2026-07-26
### Added
#### Embedded TrueType fonts
- Added `PaperForge.register_font/3` for registering embedded TrueType fonts.
- Added support for loading TrueType fonts from file paths.
- Added support for loading TrueType fonts from in-memory binaries.
- Added `PaperForge.Fonts.TrueType` for parsing compatible `.ttf` files.
- Added validation for unsupported OpenType CFF fonts.
- Added validation for invalid or truncated TrueType files.
- Added parsing for required TrueType tables:
- `head`
- `hhea`
- `maxp`
- `hmtx`
- `cmap`
- `name`
- `OS/2`
- `post`
- `loca`
- `glyf`
- Added extraction of:
- Units per em
- Glyph count
- Unicode-to-glyph mappings
- Glyph widths
- Font bounding box
- Ascent
- Descent
- Cap height
- Italic angle
- PostScript font name
- Added support for Unicode `cmap` format 4 and format 12 subtables.
- Added embedded PDF Type 0 fonts with CIDFontType2 descendants.
- Added `/Identity-H` encoding for embedded TrueType fonts.
- Added `/FontFile2` streams for embedded TrueType font programs.
- Added `/FontDescriptor` dictionaries for embedded TrueType fonts.
- Added CID width arrays from real TrueType metrics.
- Added prefixed embedded font names such as `PF0001+FontName`.
- Added subsetting of generated CID width arrays to glyphs used by the
document.
- Added subsetting of generated `/ToUnicode` CMaps to glyphs used by the
document.
- Added `PaperForge.register_font_family/3` for TrueType font families.
- Added support for `:regular`, `:bold`, `:italic`, and `:bold_italic`
TrueType family variants.
- Added document-level default font selection through `PaperForge.default_font/2`.
- Added `:default_font` support to `PaperForge.new/1`.
#### Unicode visible text
- Added visible Unicode text rendering through registered TrueType fonts.
- Added glyph-id text encoding for embedded Type 0 fonts.
- Added `/ToUnicode` CMaps for registered TrueType fonts.
- Added Unicode extraction/search support for generated embedded-font text.
- Added `PaperForge.FontError` for font registration, parsing, and glyph
errors.
- Added clear errors for unregistered font keys.
- Added clear errors when a registered TrueType font does not contain a
required glyph.
- Added support for Spanish accents, `ñ`, `ü`, inverted punctuation,
typographic symbols, Greek, and Cyrillic when the registered font contains
those glyphs.
#### Text metrics
- Added TrueType-backed width measurement in `PaperForge.TextMetrics`.
- Updated text alignment to use real TrueType glyph widths when a registered
font is used.
- Updated text wrapping and text boxes to use registered TrueType metrics.
- Updated page compilation to pass registered font instances into text
measurement and rendering.
#### Tests
- Added unit tests for TrueType parsing and metrics.
- Added unit tests for Unicode `cmap` glyph resolution.
- Added unit tests for Spanish, symbol, Greek, and Cyrillic glyph coverage.
- Added unit tests for truncated and unsupported font files.
- Added integration tests for TrueType registration from paths and binaries.
- Added integration tests for TrueType font deduplication by registered key.
- Added structural PDF tests for `/Type0`, `/CIDFontType2`, `/FontFile2`,
`/Identity-H`, and `/ToUnicode`.
- Added tests for TrueType-backed text measurement.
- Added tests for unregistered fonts and missing glyph errors.
- Added `benchmarks/truetype.exs` for TrueType registration, text measurement,
multiline rendering, and multilingual PDF generation.
- Added tests for TrueType width and `/ToUnicode` subsetting.
- Added tests for default fonts and font-family variant resolution.
- Added PDF compatibility smoke tests for multilingual documents, xref markers,
`startxref`, EOF markers, and `/ToUnicode`.
#### Document layout
- Added `PaperForge.add_flow/4` for vertical content flow.
- Added automatic page breaks for flowed text blocks.
- Added `PaperForge.Page.paragraph/3` as a paragraph-oriented text-box alias.
- Added `PaperForge.Page.table/3` for basic table rendering.
- Added `PaperForge.Page.link/3` for URI link annotations.
- Added PDF `/Annot` link dictionaries with URI actions.
- Added page `/Annots` arrays when a page contains link annotations.
- Added tests for tables, links, vertical flow, and automatic page breaks.
### Changed
- Changed unknown non-standard font keys to raise `PaperForge.FontError`
instead of a generic `ArgumentError`.
- Changed the package version to `0.3.0`.
- Updated the README to document embedded TrueType fonts, visible Unicode text,
font families, default fonts, vertical flow, tables, links, and current font
limitations.
### Limitations
- Physical TrueType table reconstruction is not implemented yet; generated PDF
width arrays and `/ToUnicode` maps are subset to used glyphs, but the full
`.ttf` program is still embedded in `/FontFile2`.
- OpenType CFF (`OTTO`) and TrueType Collection (`.ttc`) fonts are not
supported yet.
- Complex shaping for scripts such as Arabic and Devanagari is not performed
yet.
## [0.2.0] - 2026-07-26
### Added
#### Document configuration
- Added document-level configuration through `PaperForge.new/1`.
- Added the `:compress` document option.
- Enabled Flate stream compression by default.
- Added support for disabling compression with `PaperForge.new(compress: false)`.
- Added the `:pdf_version` document option with `"1.7"` as the default.
- Added validation for unsupported document options.
- Added validation for invalid compression and PDF version values.
#### Stream compression
- Added `PaperForge.Compression`.
- Added stream compression using the PDF `/FlateDecode` filter.
- Added support for streams with zero, one, or multiple filters.
- Added automatic insertion of the `/Filter` entry in stream dictionaries.
- Added compression support for page content streams.
- Preserved JPEG image data without recompressing it.
- Added tests that decompress Flate streams and verify their actual commands.
#### Fonts
- Added a built-in font registry.
- Added automatic reuse of fonts already registered in a document.
- Added on-demand font registration when pages are compiled.
- Added sequential font resource names such as `/F1`, `/F2`, and `/F3`.
- Added support for the 14 standard PDF Type 1 fonts:
- Helvetica
- Helvetica Bold
- Helvetica Oblique
- Helvetica Bold Oblique
- Times Roman
- Times Bold
- Times Italic
- Times Bold Italic
- Courier
- Courier Bold
- Courier Oblique
- Courier Bold Oblique
- Symbol
- Zapf Dingbats
- Added font family and style metadata.
- Added support for WinAnsi and built-in font encodings.
- Added `PaperForge.Font.definition_to_dictionary/1`.
- Added built-in font metrics.
- Added text-width measurement through `PaperForge.TextMetrics`.
- Added tests for font registration, font reuse, unsupported fonts, and
consecutive font resource names without relying on fixed object IDs.
#### Text layout
- Added text alignment:
- Left
- Center
- Right
- Added optional text width for alignment calculations.
- Added automatic text measurement using built-in font metrics.
- Added `PaperForge.TextWrapper`.
- Added automatic word wrapping.
- Added support for explicit newline characters.
- Added configurable line height.
- Added long-word splitting when a word exceeds the available width.
- Added `PaperForge.Graphics.TextBox`.
- Added multiline text boxes.
- Added optional text-box height limits.
- Added line-count and overflow information from text-box layout.
- Added support for text-box alignment.
- Added support for text-box fill color.
- Added support for selecting built-in fonts by atom.
#### Page coordinates and margins
- Added `PaperForge.Coordinates`.
- Added support for bottom-left page coordinates.
- Added support for top-left page coordinates.
- Added per-operation origin overrides.
- Added coordinate conversion for:
- Text
- Text boxes
- Lines
- Rectangles
- Circles
- Images
- Added `PaperForge.Margins`.
- Added uniform page margins.
- Added independent top, right, bottom, and left margins.
- Added margin validation against page dimensions.
- Added page content helpers:
- `PaperForge.Page.content_width/1`
- `PaperForge.Page.content_height/1`
- `PaperForge.Page.content_left/1`
- `PaperForge.Page.content_top/1`
- `PaperForge.Page.content_bottom/1`
- Added automatic text positioning based on page margins when `:x` or `:y`
are omitted.
#### Images
- Added JPEG image support.
- Added support for non-interlaced 8-bit grayscale, RGB, grayscale-alpha,
and RGBA PNG images.
- Added JPEG signature validation.
- Added PNG signature validation.
- Added JPEG marker parsing without decoding image pixels.
- Added PNG IHDR and IDAT parsing without decoding image pixels.
- Added extraction of:
- Width
- Height
- Bits per component
- Number of color components
- Color space
- Added support for:
- Grayscale JPEG images
- RGB JPEG images
- CMYK JPEG images
- Grayscale PNG images
- RGB PNG images
- Grayscale PNG images with alpha
- RGBA PNG images
- Added PDF image XObjects using `/DCTDecode`.
- Added PNG image XObjects using `/FlateDecode` and PNG predictor decode
parameters.
- Added PNG transparency support using PDF soft masks (`/SMask`).
- Optimized PNG parsing to avoid unnecessary per-pixel reconstruction when
the PNG can be inserted directly into the PDF.
- Added CMYK decode arrays for compatible JPEG images.
- Added `PaperForge.Image`.
- Added `PaperForge.ImageRegistry`.
- Added SHA-256-based image deduplication.
- Added sequential image resource names such as `/Im1` and `/Im2`.
- Added image loading from:
- File paths
- JPEG binaries
- PNG binaries
- Added automatic aspect-ratio preservation.
- Added image sizing using:
- Original dimensions
- Width only
- Height only
- Explicit width and height
- Added `PaperForge.Graphics.Image`.
- Added PDF image drawing using the `cm` and `Do` operators.
- Added page-level image operations through `PaperForge.Page.image/3`.
- Added tests for RGB, grayscale, CMYK, invalid, truncated, duplicated, and
distinct JPEG image handling.
- Added tests for RGB, grayscale, grayscale-alpha, RGBA, invalid, truncated,
deduplicated, and unsupported PNG image handling.
- Added PNG parsing benchmarks and large-image tests.
#### Page resources
- Added `PaperForge.PageResources`.
- Added centralized page resource management.
- Added automatic font resource dictionaries.
- Added automatic image XObject dictionaries.
- Added resource deduplication within pages.
- Added support for pages containing multiple fonts and images.
#### Metadata and string encoding
- Added `PaperForge.StringEncoding`.
- Added automatic PDF string encoding selection.
- Added literal PDF strings for compatible text.
- Added UTF-16BE encoding for Unicode metadata.
- Added Unicode support for:
- Title
- Author
- Subject
- Keywords
- Creator
- Producer
- Added creation-date metadata.
- Added modification-date metadata.
- Added PDF date serialization for:
- `DateTime`
- `NaiveDateTime`
- Added timezone-offset serialization for `DateTime` metadata.
- Added metadata option validation.
- Added omission of empty metadata values.
- Added tests for Latin-1 and UTF-16BE metadata serialization.
#### Public API
- Added `PaperForge.new/1`.
- Added page creation with options through `PaperForge.add_page/3`.
- Added support for passing an existing page to `PaperForge.add_page/2`.
- Added support for passing a page callback to `PaperForge.add_page/2`.
- Added callback return-value validation.
- Added metadata creation through `PaperForge.metadata/2`.
- Added output-path validation for `PaperForge.write/2` and
`PaperForge.write!/2`.
#### Testing
- Expanded document graph tests.
- Added tests for document compression and PDF version configuration.
- Added tests for unsupported document options.
- Added tests for invalid compression values.
- Added tests for compressed PDF output.
- Added tests for uncompressed PDF output.
- Added tests for font reuse and additional font registration.
- Added tests for JPEG and PNG parsing, image registration, image
deduplication, and image scaling.
- Added tests for top-left and bottom-left coordinate compilation.
- Added tests for margins and text-box layout behavior.
- Added tests that verify every xref offset points to the beginning of its
object.
- Added a structural round-trip style writer test covering multiple pages,
fonts, repeated images, metadata, compression, resources, and xref offsets.
- Updated writer tests so they no longer assume compressed stream contents are
visible as plain text.
- Updated document tests to use explicit PDF reference fields.
- Restored compilation with `--warnings-as-errors`.
### Changed
- Changed the default page content stream behavior to use Flate compression.
- Changed document creation to accept configuration options.
- Changed document creation so only the page tree and catalog are created
initially.
- Changed font creation to register standard Type 1 fonts only when used.
- Changed the next automatically allocated object identifier to start after the
initial page tree and catalog objects.
- Changed page compilation to register fonts and images dynamically.
- Changed page image compilation to detect supported image formats before
registering image XObjects.
- Changed page compilation to flow through `PaperForge.PageCompiler`.
- Changed page resource generation to use `PaperForge.PageResources`.
- Changed text rendering to use registered font resource names instead of a
hardcoded font resource.
- Changed text positioning to support page margins and configurable origins.
- Changed metadata values to use automatic PDF string encoding.
- Changed JPEG files to be embedded directly as PDF image streams.
- Changed the document structure to use explicit reference field names:
- `root_reference`
- `pages_reference`
- `info_reference`
- Changed tests to validate behavior and structure rather than relying on
compressed stream contents or fixed internal assumptions.
- Changed page streams to select filters from the document configuration.
- Changed multiline text rendering to use text wrapping and layout metrics.
### Fixed
- Fixed duplicate `@doc` warnings for multi-clause `PaperForge.add_page/2`.
- Fixed the missing `PaperForge.Font.definition_to_dictionary/1` function.
- Fixed JPEG bitstring matching by pinning `payload_length`.
- Fixed compilation under `mix compile --warnings-as-errors`.
- Fixed font resource reuse across pages.
- Fixed repeated image embedding by deduplicating JPEG binaries.
- Fixed repeated image embedding by deduplicating PNG binaries.
- Fixed image aspect-ratio calculations when only one dimension is provided.
- Fixed top-left coordinate conversion for box-shaped operations.
- Fixed page resource dictionaries for multiple fonts and image XObjects.
- Fixed metadata encoding for characters outside simple PDF literal-string
ranges.
- Fixed stream filter serialization for compressed page content.
- Fixed tests that referenced removed or renamed document fields.
- Fixed tests that expected uncompressed text while compression was enabled.
### Internal
- Added `PaperForge.PageCompiler` as the central page operation compiler.
- Added separate registries for fonts and images.
- Added normalized built-in font definitions.
- Added font metric tables.
- Added dedicated modules for:
- Compression
- Coordinates
- Margins
- Font registration
- Image registration
- JPEG parsing
- PNG parsing
- Page compilation
- Page resources
- String encoding
- Text measurement
- Text wrapping
- Text boxes
- Image drawing
- Continued using `iodata` for PDF command and document construction.
- Kept PDF object references separate from indirect object values.
## [0.1.0] - 2026-07-26
### Added
- Initial PaperForge project structure
- Pure Elixir PDF generation without external rendering tools
- PDF primitive serialization for:
- Null values
- Booleans
- Integers
- Floating-point numbers
- Names
- Literal strings
- Arrays
- Dictionaries
- Indirect references
- Streams
- Indirect PDF object representation
- PDF object references with generation numbers
- PDF stream support with automatic byte-length calculation
- Internal document object graph
- Automatic PDF object ID allocation
- Document catalog generation
- PDF page tree generation
- Multi-page document support
- Cross-reference table generation
- PDF trailer and `startxref` generation
- Binary PDF output
- File-writing API
- Built-in Helvetica font support using WinAnsiEncoding
- A3, A4, A5, Letter, Legal, and custom page sizes
- Portrait and landscape page orientations
- Text drawing with:
- Position
- Font size
- Fill color
- Line drawing with:
- Start and end coordinates
- Stroke color
- Configurable line width
- Rectangle drawing with:
- Stroke
- Fill
- Stroke color
- Fill color
- Configurable line width
- Circle drawing using cubic Bézier curves
- RGB color support
- 8-bit RGB color helpers
- Grayscale color support
- Basic PDF metadata:
- Title
- Author
- Subject
- Keywords
- Creator
- Producer
- Example documents for text, multiple pages, and graphics
- Unit tests for the PDF serializer, document graph, pages, and writer
### Technical details
- Uses `iodata` internally to reduce unnecessary binary concatenation
- Produces traditional PDF cross-reference tables
- Uses generation `0` for newly generated indirect objects
- Uses native PDF coordinates with the origin at the bottom-left corner
- Isolates graphic operations using the PDF `q` and `Q` operators
[0.3.0]: https://github.com/Manuel1471/paper_forge/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/Manuel1471/paper_forge/releases/tag/v0.2.0
[0.1.0]: https://github.com/Manuel1471/paper_forge/releases/tag/v0.1.0