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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 | """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 "
"column, 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 colonne, 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.")
)
)
# The page in Dutch.
DUTCH = Words(
paragraph=(
"Deze bibliotheek zet tekst door een alinea te breken in regels die in een "
"kolom passen en elke regel daarna volgens een uitlijning te plaatsen. "
"Dezelfde woorden staan hieronder links uitgelijnd, rechts uitgelijnd, "
"gecentreerd en uitgevuld, zodat het verschil in één oogopslag te zien is."
)
)
# The page in Portuguese.
PORTUGUESE = Words(
paragraph=(
"Esta biblioteca compõe o texto partindo um parágrafo em linhas que cabem "
"numa coluna e colocando depois cada linha segundo um alinhamento. As mesmas "
"palavras aparecem abaixo alinhadas à esquerda, à direita, centradas e "
"justificadas, para que a diferença se veja num relance."
)
)
# The page in Italian.
ITALIAN = Words(
paragraph=(
"Questa libreria compone il testo spezzando un paragrafo in righe che stanno "
"in una colonna, poi collocando ogni riga secondo un allineamento. Le stesse "
"parole sono mostrate qui sotto allineate a sinistra, a destra, centrate e "
"giustificate, così la differenza si vede a colpo d’occhio."
)
)
# The page in Spanish.
SPANISH = Words(
paragraph=(
"Esta biblioteca compone el texto cortando un párrafo en líneas que caben en "
"una columna y colocando luego cada línea según una alineación. Las mismas "
"palabras se muestran abajo alineadas a la izquierda, a la derecha, centradas "
"y justificadas, para que la diferencia se vea de un vistazo."
)
)
# The page in German.
GERMAN = Words(
paragraph=(
"Diese Bibliothek setzt Text, indem sie einen Absatz in Zeilen umbricht, die "
"in eine Spalte passen, und dann jede Zeile nach einer Ausrichtung platziert. "
"Dieselben Wörter stehen unten linksbündig, rechtsbündig, zentriert und im "
"Blocksatz, sodass der Unterschied zwischen ihnen auf einen Blick deutlich "
"wird."
)
)
# 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, _language.GERMAN: GERMAN, _language.SPANISH: SPANISH, _language.ITALIAN: ITALIAN, _language.PORTUGUESE: PORTUGUESE, _language.DUTCH: DUTCH}
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()
|