write_english_book.py

The Python file of the “A whole novel in English” example. A public-domain English novel read into its twelve chapters and laid out across sixty-two numbered pages, behind a contents you can click, each chapter opening a page of its own and the engine choosing every line break.

Python 54 lines

What this example is for

Most examples on this site are one page long, which says nothing about what happens at page sixty. Here the whole of Lewis Carroll's Alice's Adventures in Wonderland, published in 1865, goes in exactly as the plain text file holds it and comes out as one PDF: a title page, a contents, twelve chapters, sixty-two numbered pages. The program is told one thing and one thing only about that text — that a line reading CHAPTER I opens a chapter — and every heading, every running head and every page number follows from it.

What this example shows

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""Lays a whole English novel out and writes it as one PDF.

The Python twin of the `write_english_book` example in Rust.

It is what a document's weight really looks like. A novel draws the whole
alphabet in both cases, the digits and the punctuation, so the embedded font
carries far more outlines than an invoice does -- and its metrics, which used to
be stated for every glyph of the face, are stated only for the glyphs the book
draws.

Its twin, `write_french_book`, lays another novel out through the same code. Neither
is a translation of the other: each is a book of its own, and each says how its own
file marks a chapter.

Usage: python examples/write_english_book.py [out.pdf] [font.ttf]
"""

from __future__ import annotations

import _book
import _licence
import _out

import hqf_pdf

BOOK = _book.Book(
    title="Alice's Adventures in Wonderland",
    author="Lewis Carroll",
    file="wonderland.txt",
    mark_before="CHAPTER ",
    mark_after=".",
    chapters=12,
    contents_title="Contents",
)


def main() -> None:
    out = _out.output_path("english_book")

    document = hqf_pdf.Document()
    document.set_license(_licence.licensed())
    handle = document.add_font(hqf_pdf.Font.from_path(_out.font_path()))

    text = BOOK.path().read_text(encoding="utf-8")
    _book.lay_out(document, handle, BOOK, text)

    data = document.to_bytes()
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_bytes(data)
    print(f"wrote {out}: {len(data)} bytes")


if __name__ == "__main__":
    main()