Metadata-Version: 2.5
Name: pdf_io
Version: 0.1.0
Summary: Create PDFs in pure Python: drawing APIs, SVG conversion 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
Description-Content-Type: text/markdown

# pdf_io

Create PDF files in pure Python: convert SVG, draw pages, plot data.
Standard library only; numpy is optional and used only for rasterization.

![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 or PNG.
* **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; heatmaps through bundled or custom colormaps.

## Install

```sh
pip install .
```

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

## 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).

## numpy (optional)

numpy is imported only by the features that produce pixels:

* rasterized groups (`rasterize=True`, `data-rasterize`), stored lossless or
  as JPEG (`jpeg_quality=85`);
* fast rendering of large marker sets inside rasterized groups;
* SVG filters, which are off by default (`filters=True`);
* PNG export.

Without numpy these raise `RasterizationError`. Everything else needs only
the standard library.

## 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.
Rasterization tests are skipped when numpy is missing.

```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 (numpy)
```

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

```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).
