Metadata-Version: 2.5
Name: pdf_io
Version: 0.3.0
Summary: Create PDFs in Python: drawing APIs, SVG conversion, rasterization and more
Project-URL: Repository, https://github.com/ajgouhier/pdf_io
Author-email: Arthur Gouhier <ajgouhier@gmail.com>
License-Expression: BSD-3-Clause
License-File: LICENSE
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: flake8; extra == 'dev'
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: ziglang==0.15.1; extra == 'dev'
Description-Content-Type: text/markdown

# pdf_io

Create PDF files in Python: convert SVG, draw pages, plot data, render PNG or JPEG.
No dependencies: a bundled C library does the heavy lifting.

![showcase](examples/showcase.png)

* **Convert** SVG to PDF: shapes, paths, text with embedded font subsets,
  gradients, patterns, clipping, masks, markers, images and CSS.
* **Draw a scene** with `pdf_io.draw` (drawsvg-style) and save it as PDF,
  SVG, PNG or JPEG.
* **Draw on pages** with `Document` and `Canvas` (HTML-canvas-style):
  multiple pages, links, bookmarks, metadata, placed SVG files.
* **Lay out text**: paragraphs in boxes, justified or not, greedy or
  Knuth–Plass line breaking, kerning, ligatures, rich text with links,
  overflow into further boxes.
* **Print and archive**: CMYK output, spot colors (Separation), ink limit,
  ICC output intent; PDF/A-2b, 2u and 3b with file attachments.
* **Plot**: markers at many points, each with its own shape, size, colors
  and opacity; lines of millions of points; heatmaps through bundled or
  custom colormaps.  Coordinates are sequences or any buffer (`array`,
  numpy arrays, ...).  `simplify` leaves out what later points hide and
  decimates long lines, within half a level per pixel.
* **Rasterize** groups, SVG filters and whole pages (PNG, JPEG) with the same
  rendering as the PDF.

## Install

```sh
pip install .
```

Python 3.11+. No dependencies. Copying the `pdf_io/` directory into a project
also works.

The C library is bundled, prebuilt for Linux (x86_64, aarch64), Windows
(x86_64, arm64) and macOS (arm64); pip compiles nothing.  On other platforms,
build it with `tools/build_native.py` and point `PDF_IO_NATIVE_LIB` at it;
without it, plain vector drawing still works and the bulk features (markers,
lines, heatmaps, rasterization, PNG, image decoding) raise
`NativeLibraryError`.

## Quick start

```python
import pdf_io

pdf_io.convert_file("drawing.svg")                 # writes drawing.pdf
pdf_bytes = pdf_io.svg_to_pdf(svg_text)
```

```sh
pdf_io drawing.svg out.pdf
```

```python
import pdf_io.draw as draw

d = draw.Drawing(400, 300)                         # CSS pixels, origin top-left
d.append(draw.Circle(200, 150, 80, fill="teal"))
d.append(draw.Text("Hello", 32, 200, 160, text_anchor="middle", fill="white"))
d.save_pdf("hello.pdf")
d.save_svg("hello.svg")
```

```python
from pdf_io import Document

doc = Document(title="Report")
page = doc.add_page(size="A4")                     # points, origin top-left
page.font_size = 24
page.fill_text("Report", 50, 80)
page.draw_markers(xs, ys, "circle", size=4, fill="steelblue", stroke=None)
page.draw_heatmap(values, 50, 300, 400, 250, cmap="viridis")
doc.save("report.pdf")
```

## Documentation

* [API.md](API.md): the complete API, supported SVG features, fonts,
  rasterization and limits.
* [EXAMPLES.md](EXAMPLES.md): worked examples (scatter plot, bubble chart,
  heatmap, multi-page document, rasterization, filters, PNG).

## Limits

* Text: no complex-script shaping or bidirectional reordering. Kerning and
  ligatures apply to laid-out paragraphs only.
* Fonts: WOFF2 and CFF2 (variable OpenType) fonts are not supported.
* Filters can only be reproduced as pixels, so they are opt-in.
* Animation and scripting are ignored: the initial state is drawn.

## Development

```sh
python -m unittest discover -s tests -t tests
```

Tests generate their own fonts and images and ignore installed fonts.

```sh
mypy                                       # type check (configured in pyproject.toml)
```

The package ships type annotations (`py.typed`); mypy is a development tool
only.

```sh
python tools/regress.py --render --check   # output vs. HEAD on tests/corpus
python tools/regress.py --base main --system
python tools/bench.py                      # timings quoted in API.md
```

`regress.py` converts every SVG of the corpus with the working tree and with
a git revision and compares the page content streams and rasterized images
byte for byte; `--render` reports pixel differences of changed files and
`--check` reports files poppler warns about.

```sh
pip install ziglang==0.15.1                # or: pip install -e .[dev]
python tools/build_native.py               # rebuild pdf_io/_native/bin/*
python tools/build_native.py --check       # binaries match the sources, byte for byte
python tools/crosscheck.py --qemu qemu-aarch64-static   # same pixels on x86_64 and aarch64
```

The C library and its rules (no libc, no imports, deterministic floating
point) are described in [pdf_io/_native/README.md](pdf_io/_native/README.md),
with the sanitizer build and the fuzzers (`tests/fuzz_native.py`).

```sh
python tools/verapdf.py                    # PDF/A validation of the corpus
```

`verapdf.py` converts the corpus at each PDF/A level and validates the files
with [veraPDF](https://verapdf.org) (on `PATH` or `--verapdf`); the PDF/A
unit tests also run veraPDF when it is on `PATH`.

## License

BSD 3-Clause, see [LICENSE](LICENSE).
