Skip to content

Commit

Permalink
📥 Add support for embedded fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
ariebovenberg committed Dec 1, 2022
1 parent b6c17e4 commit e2e719b
Show file tree
Hide file tree
Showing 23 changed files with 1,595 additions and 314 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,4 @@ Temporary Items
.envrc
*.csv
*.pdf
output/
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

0.2.0 (2022-12-01)
------------------

- 🖌️ Different builtin fonts can be selected
- 📥 Truetype fonts can be embedded
- 📐 Pages can be rotated
- 🤏 Compression is applied to keep filesize small

0.1.0 (2022-11-02)
------------------

Expand Down
16 changes: 12 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,26 @@

**PDF·je** [PDF·yuh] *(noun)* Dutch for 'small PDF'

Tiny library for writing simple PDFs. Experimental.
Tiny library for writing simple PDFs.

Currently under development.
The API may change significantly until the 1.x release.
Leave a ⭐️ on GitHub if you're interested how this develops!

Why?
----

The most popular libraries for writing PDFs are quite old and inspired by Java and PHP.
*PDFje* is a modern, Pythonic library with a more declarative API.
The most popular Python libraries for writing PDFs are quite old
and inspired by Java and PHP. **PDFje** is a modern, Pythonic library with
a more declarative API.

How does it work?
-----------------

.. code-block:: python
>>> from pdfje import Document, Page, Text
>>> pdf.Document([
>>> Document([
... Page([Text("Hello", at=(200, 700)), Text("World", at=(300, 670))]),
... Page(),
... Page([Text("This is the last page!", at=(300, 600))]),
Expand All @@ -53,3 +55,9 @@ It's available on PyPI.
.. code-block:: bash
pip install pdfje
Development
-----------

- Install dependencies with ``poetry install``.
- To write output files during tests, use ``pytest --output-path=<outpur-dir>``
76 changes: 76 additions & 0 deletions docs/guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
User guide
==========

Documents and pages
-------------------

PDF documents consist of pages, which may have graphical context (e.g. text).
Below shows an example of creating a document and writing it to a file.

.. code-block:: python
>>> from pdfje import Document, Page, Text
>>> Document([
... Page([Text("Hello", at=(200, 700)), Text("World", at=(300, 670))]),
... Page(), # empty page
... Page([Text("This is the last page!", at=(300, 600))]),
... ]).to_path('hello.pdf')
Fonts and unicode
-----------------

There are two types of fonts:

1. **Standard fonts** are included in all PDF readers.
The downside is that these fonts only support a very
limited set of unicode characters.
The standard fonts are:

- Helvetica
- Times Roman
- Courier
- Symbol
- ZapfDingBats

Below is an example of using different standard fonts:

.. code-block:: python
>>> from pdfje import Text, courier, helvetica
>>> Text("Hello Helvetica", font=helvetica)
>>> Text("Ciao, Courier", font=courier)
.. warning::

The standard fonts only support characters within the ``cp1252`` encoding
(i.e. ASCII plus some common western european characters).
This is a limitation of the PDF format, not ``pdfje``.
Characters outside this set will be displayed as ``?``.
If you need broader unicode support,
you will need to use :ref:`an embedded font<embedded-fonts>`.

.. _embedded-fonts:

2. **Embedded fonts** are included in the PDF file itself.
To use an embedded font, you will need to download its TrueType
(``.ttf``) font file and tell ``pdfje`` where to find it.

Here is an example of using the DejaVu font

.. code-block:: python
>>> from pdfje import Text, Font
>>> dejavu = Font.from_path("path/to/DejaVuSansCondensed.ttf")
>>> Text("We meet again, DejaVu!", font=dejavu)
.. note::

To save space, only the parts of the font that are actually used will
be embedded in the document.
This standard practice is called "subsetting".

.. note::

Any unicode characters for which a font has no representation
will be displayed as a 'missing character' box.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Contents
.. toctree::
:maxdepth: 2

guide.rst
api.rst


Expand Down
3 changes: 3 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ enable_error_code = redundant-expr
check_untyped_defs = True
disallow_untyped_defs = False
warn_unreachable = True

[mypy-fontTools.*]
ignore_missing_imports = True
115 changes: 96 additions & 19 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e2e719b

Please sign in to comment.