tenderness is a fast library for synthetic, deterministic document rendering from text and images, powered by Cairo and Pango.
Why tenderness?
Most document datasets don’t come from real structure — they come from reconstruction. Text is rendered, then reverse-engineered back into layout using OCR, heuristics, or fragile parsing pipelines. The result is noisy, incomplete, and not reproducible.
tenderness flips this entirely.
It renders text directly into documents producing images, SVGs, and PDFs with fully known layout from the start. Every character placement, line break, and block position is defined at render time — not inferred afterward.
What this gives you
- Generate large-scale synthetic document datasets
- Provide precise structural supervision for vision-language models
- Build benchmarks for layout understanding systems
- Ground-truth layout across characters, clusters, runs, and lines
No OCR. No heuristics. No reconstruction. No manual annotation.
Just text in → fully structured document out.
Main Features
-
Multi-format output: Render text and images into Image, SVG, PDF, or NumPy arrays.
-
Composable content blocks: Build documents from simple primitives:
TextBlock,ImageBlock, andTableBlock. -
Minimal flexbox layout engine: A lightweight system that automatically resolves positioning and flow.
-
Exact bounding boxes (OBB + AABB, logical + ink): Extract multi-level data for text (character, cluster, run, line, layout) and blocks.
-
Rich typography & text flow: Custom fonts, hierarchical styling, Pango markup, automatic font fallback, and overflow-aware text continuation across blocks.
-
Composable pipelines: Use the built-in pipeline with pre-defined layouts, or build your own from scratch.
Quick Start
pip install tenderness
import pathlib
from tenderness.cairo_backend.color_patterns import SolidColorSpec
from tenderness.cairo_backend.surface_config_manager import SurfaceConfigManager
from tenderness.colors.color_selector import ColorSelector
from tenderness.pango_backend.font_description_interface import FontDescriptionInterfaceParameters
from tenderness.pipelines.document import (
DocumentBlocksConfig,
DocumentConfig,
DocumentRenderPipeline,
TextBlock,
TextStyle,
)
# select colors
color_selector = ColorSelector()
white = SolidColorSpec(color=color_selector.by_names(["white"])[0])
black = SolidColorSpec(color=color_selector.by_names(["black"])[0])
# select surface (image, pdf, svg, etc.)
img_surface_config = SurfaceConfigManager().create_image_surface_config(
width=400,
height=100,
)
# create document config and blocks config
doc_config = DocumentConfig(surface_config=img_surface_config, background_spec=white)
doc_blocks_config = DocumentBlocksConfig(
surface_config=img_surface_config,
blocks=[
TextBlock(
text="Hello, world!",
text_style=TextStyle(
font_description_params=FontDescriptionInterfaceParameters(size=32),
text_color_spec=black,
),
),
],
)
# create pipeline and render document
pipeline = DocumentRenderPipeline()
setup_result = pipeline.setup(config=doc_config)
render_result = pipeline.render(
blocks_config=doc_blocks_config,
setup_result=setup_result,
)
# save the rendered document to a file
pipeline.save_as_file(
surface=setup_result.surface,
surface_config=img_surface_config,
output_file_path=pathlib.Path("hello_world"),
)
# The output file will be saved as `hello_world.png` in the current working directory.
You can find the runnable version at scripts/mini_example.py, and more examples over at tenderness-examples. If you run into missing system libraries (Cairo, Pango, PyGObject), check the install guide.
Metadata
Release files for tenderness 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tenderness-0.3.0.tar.gz | 113.3 kB | Without provenance | Details for tenderness-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tenderness-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for tenderness-0.3.0-py3-none-any.whl |
Total release size: 292.5 kB
Release files / tenderness-0.3.0.tar.gz
| Download URL | tenderness-0.3.0.tar.gz |
|---|---|
| Size | 113.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
898d5364ad33b17da1f08ab0f964e6951778f625aa365aa533d0faccaf821d37
|
|
BLAKE2b-256 checksum How to use checksums |
b0b6547660cd31cb06b720d41e405fa127928151e841aac8d7f95fd26a19c749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / tenderness-0.3.0-py3-none-any.whl
| Download URL | tenderness-0.3.0-py3-none-any.whl |
|---|---|
| Size | 179.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a9f0044d554d62c34da33d9e1002a7153ece91a1e3cdcb4752b0c75db9bf2dba
|
|
BLAKE2b-256 checksum How to use checksums |
02817f6b81691b5650f36e8825b0c004151b8d1eef226e13142075678a866b87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for tenderness 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.