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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 | """Lays a paragraph out four ways, to see the alignment.
The Python twin of the `write_flow` example in Rust. The paragraph is held in `Words`,
once per language, and `HQF_PDF_LANG` picks which one is laid out.
Usage: python examples/write_flow.py [out.pdf] [font.ttf]
HQF_PDF_LANG=fr python examples/write_flow.py
"""
from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
import _language
import _licence
import _out
import hqf_pdf
@dataclass(frozen=True)
class Words:
"""Every word the page lays out, in one language."""
# The paragraph the four alignments are shown on.
paragraph: str
# The page in English.
ENGLISH = Words(
paragraph=(
"This library lays text out by breaking a paragraph into lines that fit a "
"box, then placing each line according to an alignment. The same words are "
"shown below flush left, flush right, centred, and justified, so the "
"difference between them is plain to see at a glance."
)
)
# The page in French.
FRENCH = Words(
paragraph=(
"Cette bibliothèque met le texte en page en découpant un paragraphe en "
"lignes qui tiennent dans une boîte, puis en plaçant chaque ligne selon un "
"alignement. Les mêmes mots sont repris ci-dessous alignés à gauche, alignés "
"à droite, centrés, puis justifiés, pour que la différence entre eux se voie "
"d'un seul coup d'œil."
)
)
# Every language the example is written in. A language is added by writing its own set
# of words and naming it here.
WORDS = {_language.ENGLISH: ENGLISH, _language.FRENCH: FRENCH}
def main() -> None:
language = _language.from_environment()
words = _language.words_of(WORDS, language)
# A named file is written as named; the default one carries the language, so the two
# languages do not overwrite each other in `tmp/`.
out = _out.output_path(Path(_language.file_name("flow.pdf", language)).stem)
document = hqf_pdf.Document()
document.set_license(_licence.licensed())
handle = document.add_font(hqf_pdf.Font.from_path(_out.font_path()))
content = hqf_pdf.Content()
box_width = 400.0
x = 80.0
top = 780.0
for align in (
hqf_pdf.Align.Left,
hqf_pdf.Align.Right,
hqf_pdf.Align.Center,
hqf_pdf.Align.Justify,
):
flow = hqf_pdf.TextFlow(handle, 11.0, align=align, leading=15.0)
lines = flow.break_lines(words.paragraph, box_width)
flow.draw(content, lines, x, top, box_width)
# A frame around the text column, inset from the glyphs on every side.
height = flow.height(lines)
pad = 8.0
content.save_state()
content.set_stroke(hqf_pdf.Rgb.gray(0.8))
content.set_line_width(0.5)
content.rect(
x - pad,
top - height - pad,
box_width + pad * 2.0,
height + pad * 2.0,
)
content.stroke()
content.restore_state()
top -= height + 30.0
page = hqf_pdf.Page.a4()
page.set_content(content)
document.add_page(page)
written = document.write(out)
print(f"wrote {out}: {written} bytes")
if __name__ == "__main__":
main()
|