-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathalphabetProof.py
289 lines (221 loc) · 7.93 KB
/
alphabetProof.py
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# Copyright 2023 Adobe
# All Rights Reserved.
# NOTICE: Adobe permits you to use, modify, and distribute this file in
# accordance with the terms of the Adobe license agreement accompanying
# it.
'''
Creates example pages for:
- general alphabet (upper- and lowercase)
- spacing proofs
- some sample words
Modes (`proof`, `spacing`, `sample`) can be chosen individually, or all at once
(`all`). Writing systems supported are `lat`, `grk`, `cyr`, and `figures`.
Input: one or more font files.
'''
import os
import argparse
import subprocess
import drawBot as db
from proofing_helpers.stamps import timestamp
from proofing_helpers.files import get_font_paths, make_temp_font
from proofing_helpers.fontSorter import sort_fonts
class RawDescriptionAndDefaultsFormatter(
# https://stackoverflow.com/a/18462760
argparse.ArgumentDefaultsHelpFormatter,
argparse.RawDescriptionHelpFormatter
):
pass
def get_options():
mode_choices = ['proof', 'spacing', 'sample', 'all']
ws_choices = ['lat', 'grk', 'cyr', 'figures', 'all']
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=RawDescriptionAndDefaultsFormatter
)
parser.add_argument(
'-m', '--mode',
action='store',
default='proof',
choices=mode_choices,
help='mode')
parser.add_argument(
'-w', '--writing_system',
action='store',
default='lat',
choices=ws_choices,
help='writing system')
parser.add_argument(
'-s', '--string',
action='store',
help='custom string',
default=None,)
parser.add_argument(
'-p', '--point_size',
default=60,
action='store',
type=int,
help='font size')
parser.add_argument(
'-k', '--kerning_off',
default=False,
action='store_true',
help='switch off kerning')
parser.add_argument(
'-d', '--date',
action='store_true',
help='date proof document')
parser.add_argument(
'-t', '--text',
action='store',
help='read custom file')
parser.add_argument(
'input',
nargs='+',
help='input font file(s)')
return parser.parse_args()
def read_text_file(file_path):
'''
Read a custom text file.
This file is expected to indicate page breaks with a double linebreak.
'''
with open(file_path, 'r') as blob:
pages = blob.read().split('\n\n')
return pages
def read_sample_text(kind='sample', w_system='lat'):
if kind == 'all':
chunks = []
for option in ['proof', 'spacing', 'sample']:
chunks.extend(read_sample_text(option, w_system))
return chunks
if w_system == 'all':
chunks = []
for system in ['lat', 'grk', 'cyr', 'figures']:
chunks.extend(read_sample_text(kind, system))
return chunks
else:
assets_path = os.path.dirname(__file__)
text_dir = os.path.join(assets_path, '_content', 'alphabet proof')
text_file_name = f'{kind}_{w_system}.txt'
text_path = os.path.join(assets_path, text_dir, text_file_name)
if os.path.exists(text_path):
with open(text_path, 'r') as tf:
pages = tf.read().split('\n\n\n')
chunks = []
for page in pages:
filtered_page = [
line for line in page.split('\n') if
line and not
line.strip().startswith('#')]
if filtered_page:
chunks.append('\n'.join(filtered_page))
return chunks
else:
print(text_path, 'does not exist')
def make_proof(args, input_paths, output_path):
if args.text:
if os.path.exists(args.text):
proof_text = read_text_file(args.text)
else:
mode = args.mode.lower()
custom_string = args.string
writing_system = args.writing_system.lower()
proof_text = make_proof_text(mode, writing_system, custom_string)
db.newDrawing()
assets_path = os.path.dirname(__file__)
ADOBE_BLANK = db.installFont(os.path.join(
assets_path, '_fonts/AdobeBlank.otf'))
FONT_MONO = os.path.join(
assets_path, '_fonts/SourceCodePro-Regular.otf')
MARGIN = 30
line_space = args.point_size * 1.2
base_names = [os.path.basename(font) for font in input_paths]
if len(input_paths) == 1:
font_paths = input_paths
else:
font_paths = [
make_temp_font(input_index, input_path) for
(input_index, input_path) in enumerate(input_paths)]
for page in proof_text:
feature_dict = {'kern': not args.kerning_off}
# undocumented feature -- it is possible to add feature tags
# to the input text files. Not sure how useful.
#
# if page.startswith('#'): # features
# page_lines = page.splitlines()
# feature_line = page_lines[0].strip('#').strip()
# feature_dict = {
# feature_name: True for feature_name in feature_line.split()}
# page = '\n'.join(page_lines[1:])
for font_index, font in enumerate(font_paths):
font_name = base_names[font_index]
db.newPage('LetterLandscape')
fs_stamp = db.FormattedString(
f'{font_name}',
font=FONT_MONO,
fontSize=10,
align='right')
if args.kerning_off:
fs_stamp += ' | no kerning'
fs_stamp += f' | {timestamp(readable=True)}'
db.textBox(fs_stamp, (0, MARGIN, db.width() - MARGIN, 20))
y_offset = db.height() - MARGIN - args.point_size
for line in page.split('\n'):
fs = db.FormattedString(
line,
font=font,
fontSize=args.point_size,
fallbackFont=ADOBE_BLANK,
openTypeFeatures=feature_dict,
)
db.text(fs, (MARGIN, y_offset))
if len(line) == 0:
y_offset -= line_space / 2
else:
y_offset -= line_space
db.saveImage(output_path)
db.endDrawing()
def make_proof_text(mode, writing_system, custom_string=None):
proof_text = []
if custom_string:
proof_text.extend([custom_string])
proof_text.extend(read_sample_text(mode, 'lat'))
else:
proof_text.extend(read_sample_text(mode, writing_system))
if writing_system not in ['all', 'figures']:
# add the figures for good measure
proof_text.extend(read_sample_text(mode, 'figures'))
return proof_text
def get_input_paths(input):
'''
Find if the input argument is a folder or a/multiple file(s).
Return either just the file, or get font paths within folders.
'''
if len(args.input) == 1 and os.path.isdir(input[-1]):
return sort_fonts(get_font_paths(input[-1]), True)
return input
def make_output_name(args):
'''
Try to make a sensible filename for the PDF proof created.
'''
if len(args.input) == 1 and os.path.isdir(args.input[-1]):
input_paths = get_font_paths(args.input[-1])
else:
input_paths = args.input
all_font_names = [
os.path.splitext(os.path.basename(font))[0] for font in input_paths
]
font_name_string = ' vs '.join(all_font_names)
if len(font_name_string) > 200:
font_name_string = 'comparison of many fonts'
name_chunks = [font_name_string, args.mode, args.writing_system]
if args.date:
name_chunks.insert(0, timestamp())
return ' '.join(name_chunks) + '.pdf'
if __name__ == '__main__':
args = get_options()
input_paths = get_input_paths(args.input)
output_path = (os.path.join(
os.path.expanduser('~/Desktop'),
make_output_name(args)))
make_proof(args, input_paths, output_path)
subprocess.call(['open', output_path])