-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtext_align_justify
executable file
·134 lines (128 loc) · 4.83 KB
/
text_align_justify
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
#!/usr/bin/python3
#+
# Demonstration of basic (non-contextual, left-to-right) text layout,
# with horizontal alignment and justification.
#
# Copyright 2015 by Lawrence D'Oliveiro <[email protected]>. This
# script is licensed CC0
# <https://creativecommons.org/publicdomain/zero/1.0/>; do with it
# what you will.
#-
import sys
import os
import qahirah as qah
from qahirah import \
CAIRO, \
Colour, \
Glyph, \
Rect, \
Vector
def align_text(g, text_lines, line_width, align) :
"renders the sequence of text_lines horizontally-aligned within line_width according" \
" to align: 0 for left-aligned, 0.5 for centred, 1.0 for right-aligned; in-between" \
" values also allowed. Returns the bounds of the rendered text."
font_extents = g.font_extents
bounds = Rect.empty
for line in text_lines :
save_pos = g.current_point
extents = g.text_extents(line)
if align != 0 :
text_width = extents.width
g.rel_move_to(((line_width - text_width) * align, 0))
#end if
bounds |= Rect(extents.x_bearing, extents.y_bearing, extents.width, extents.height) + g.current_point
g.show_text(line)
g.move_to(save_pos + Vector(0, font_extents.height))
#end for
return \
bounds
#end align_text
def justify_text(g, text_lines, line_width, space_extra) :
"renders the sequence of text_lines with full justification within line_width." \
" space_extra is the relative amount of extra spacing to give to space glyphs; 0" \
" means to treat them the same as non-space glyphs."
space_glyph = g.scaled_font.text_to_glyphs((0, 0), " ", cluster_mapping = False)[0][0].index
#sys.stderr.write("space_glyph = {}\n".format(space_glyph)) # debug
font_extents = g.font_extents
for line in text_lines :
save_pos = g.current_point
glyphs = g.scaled_font.text_to_glyphs(save_pos, line, cluster_mapping = False)[0]
nr_spaces = len(tuple(g for g in glyphs if g.index == space_glyph))
glyph_extents = g.glyph_extents(glyphs)
glyph_adjust = \
(
(line_width - glyph_extents.width)
/
(len(glyphs) + nr_spaces * space_extra - 1)
)
# subtract 1 because no adjustment for first char on line, count of nr_spaces
# assumes none are at beginning or end of line!
new_glyphs = []
prev_pos_x = 0
prev_adj_pos_x = 0
for i, glyph in enumerate(glyphs) :
if i == 0 :
adjust = 0
elif glyph.index == space_glyph :
adjust = glyph_adjust * (1 + space_extra)
else :
adjust = glyph_adjust
#end if
adj_pos_x = glyph.pos.x - prev_pos_x + prev_adj_pos_x + adjust
new_glyphs.append \
(
Glyph(index = glyph.index, pos = (adj_pos_x, glyph.pos.y))
)
prev_pos_x = glyph.pos.x
prev_adj_pos_x = adj_pos_x
#end for
g.show_glyphs(new_glyphs)
g.move_to(save_pos + Vector(0, font_extents.height))
#end for
#end justify_text
text_lines = \
(
"Lorem ipsum dolor sit amet, consectetur",
"adipiscing elit, sed do eiusmod tempor",
"incididunt ut labore et dolore magna aliqua.",
"Ut enim ad minim veniam, quis nostrud",
"exercitation ullamco laboris nisi ut aliquip",
"ex ea commodo consequat. Duis aute irure dolor",
"in reprehenderit in voluptate velit esse cillum",
"dolore eu fugiat nulla pariatur. Excepteur sint",
"occaecat cupidatat non proident, sunt in culpa",
"qui officia deserunt mollit anim id est laborum.",
)
text_size = 18
height_fudge = 1.4
line_width = text_size * 25
margin = 30
pix = qah.ImageSurface.create \
(
format = CAIRO.FORMAT_RGB24,
dimensions = round(Vector
(
line_width * 2 + margin * 3,
text_size * (len(text_lines) * 3 + 1) * height_fudge + margin * 4
))
)
g = qah.Context.create(pix)
g.set_source_colour(Colour.grey(1)).set_operator(CAIRO.OPERATOR_SOURCE).paint()
g.set_source_colour(Colour.grey(0))
g.font_face = qah.FontFace.create_for_pattern("century schoolbook")
g.set_font_size(text_size)
font_extents = g.font_extents
g.move_to((margin, font_extents.ascent - font_extents.height + margin))
for align in (0, 0.5, 1.0) :
g.rel_move_to((0, font_extents.height))
bounds = align_text(g, text_lines, line_width, align)
#sys.stderr.write("bounds = {}\n".format(bounds)) # debug
#end for
g.move_to((2 * margin + line_width, font_extents.ascent - font_extents.height + margin))
for space_extra in (0, 3, 10) :
g.rel_move_to((0, font_extents.height))
justify_text(g, text_lines, line_width, space_extra)
#end for
pix \
.flush() \
.write_to_png("%s.png" % os.path.basename(sys.argv[0]))