foundrytools-cli 2.2.0__py3-none-any.whl → 2.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- foundrytools_cli/__init__.py +1 -1
- foundrytools_cli/commands/font.py +40 -0
- foundrytools_cli/commands/otf.py +71 -16
- {foundrytools_cli-2.2.0.dist-info → foundrytools_cli-2.2.1.dist-info}/METADATA +2 -2
- {foundrytools_cli-2.2.0.dist-info → foundrytools_cli-2.2.1.dist-info}/RECORD +7 -7
- {foundrytools_cli-2.2.0.dist-info → foundrytools_cli-2.2.1.dist-info}/WHEEL +0 -0
- {foundrytools_cli-2.2.0.dist-info → foundrytools_cli-2.2.1.dist-info}/entry_points.txt +0 -0
foundrytools_cli/__init__.py
CHANGED
|
@@ -11,6 +11,46 @@ from foundrytools_cli.utils.task_runner import TaskRunner
|
|
|
11
11
|
cli = click.Group(help="Font level utilities.")
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
@cli.command("add-extremes", cls=BaseCommand)
|
|
15
|
+
@click.option(
|
|
16
|
+
"--keep-hinting",
|
|
17
|
+
is_flag=True,
|
|
18
|
+
help="Preserve hinting when adding extrema points.",
|
|
19
|
+
)
|
|
20
|
+
@click.option(
|
|
21
|
+
"--tolerance",
|
|
22
|
+
type=click.FloatRange(min=0),
|
|
23
|
+
default=1.0,
|
|
24
|
+
show_default=True,
|
|
25
|
+
help="Do not add extrema points within this distance (font units) of existing points.",
|
|
26
|
+
)
|
|
27
|
+
def add_extremes(input_path: Path, **options: dict[str, Any]) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Add points at the horizontal and vertical extrema of glyph curves.
|
|
30
|
+
|
|
31
|
+
Composite glyphs in TrueType fonts and variable fonts are not modified.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def task(font: Font, keep_hinting: bool = False, tolerance: float = 1.0) -> bool:
|
|
35
|
+
modified_glyphs = font.add_extremes(
|
|
36
|
+
remove_hinting=not keep_hinting,
|
|
37
|
+
tolerance=tolerance,
|
|
38
|
+
)
|
|
39
|
+
if not modified_glyphs:
|
|
40
|
+
logger.info("No glyphs were modified")
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
logger.opt(colors=True).info(
|
|
44
|
+
f"{len(modified_glyphs)} glyphs were modified: "
|
|
45
|
+
f"<lc>{', '.join(sorted(modified_glyphs))}</lc>"
|
|
46
|
+
)
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
runner = TaskRunner(input_path=input_path, task=task, **options)
|
|
50
|
+
runner.filter.filter_out_variable = True
|
|
51
|
+
runner.run()
|
|
52
|
+
|
|
53
|
+
|
|
14
54
|
@cli.command("correct-contours", cls=BaseCommand)
|
|
15
55
|
@click.option(
|
|
16
56
|
"-ma",
|
foundrytools_cli/commands/otf.py
CHANGED
|
@@ -258,12 +258,53 @@ def round_coordinates(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
258
258
|
The number of vertical stem values to extract.
|
|
259
259
|
""",
|
|
260
260
|
)
|
|
261
|
+
@click.option(
|
|
262
|
+
"--use-samples/--all-glyphs",
|
|
263
|
+
default=True,
|
|
264
|
+
show_default=True,
|
|
265
|
+
help="Calculate each value from its default or custom glyph sample, or from the whole font.",
|
|
266
|
+
)
|
|
267
|
+
@click.option(
|
|
268
|
+
"--std-h-sample",
|
|
269
|
+
multiple=True,
|
|
270
|
+
help="Characters to sample for StdHW; may be repeated. Defaults to the built-in sample.",
|
|
271
|
+
)
|
|
272
|
+
@click.option(
|
|
273
|
+
"--std-v-sample",
|
|
274
|
+
multiple=True,
|
|
275
|
+
help="Characters to sample for StdVW; may be repeated. Defaults to the built-in sample.",
|
|
276
|
+
)
|
|
277
|
+
@click.option(
|
|
278
|
+
"--snap-h-sample",
|
|
279
|
+
multiple=True,
|
|
280
|
+
help="Characters to sample for StemSnapH; may be repeated. Defaults to the built-in sample.",
|
|
281
|
+
)
|
|
282
|
+
@click.option(
|
|
283
|
+
"--snap-v-sample",
|
|
284
|
+
multiple=True,
|
|
285
|
+
help="Characters to sample for StemSnapV; may be repeated. Defaults to the built-in sample.",
|
|
286
|
+
)
|
|
261
287
|
def recalc_stems(input_path: Path, **options: dict[str, Any]) -> None:
|
|
262
288
|
"""
|
|
263
289
|
Recalculate the hinting stems of OpenType-PS fonts.
|
|
264
290
|
"""
|
|
265
291
|
|
|
266
|
-
|
|
292
|
+
sample_options = ("std_h_sample", "std_v_sample", "snap_h_sample", "snap_v_sample")
|
|
293
|
+
if not options["use_samples"] and any(options[name] for name in sample_options):
|
|
294
|
+
raise click.UsageError("Custom glyph samples cannot be used with --all-glyphs.")
|
|
295
|
+
|
|
296
|
+
def task(
|
|
297
|
+
font: Font,
|
|
298
|
+
report_all_stems: bool = False,
|
|
299
|
+
max_distance: int = 1,
|
|
300
|
+
max_h_stems: int = 2,
|
|
301
|
+
max_v_stems: int = 2,
|
|
302
|
+
use_samples: bool = True,
|
|
303
|
+
std_h_sample: tuple[str, ...] = (),
|
|
304
|
+
std_v_sample: tuple[str, ...] = (),
|
|
305
|
+
snap_h_sample: tuple[str, ...] = (),
|
|
306
|
+
snap_v_sample: tuple[str, ...] = (),
|
|
307
|
+
) -> bool:
|
|
267
308
|
if not font.is_ps:
|
|
268
309
|
logger.error("Font is not a PostScript font")
|
|
269
310
|
return False
|
|
@@ -273,11 +314,17 @@ def recalc_stems(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
273
314
|
return False
|
|
274
315
|
|
|
275
316
|
flavor = font.ttfont.flavor
|
|
276
|
-
temp_file =
|
|
317
|
+
temp_file: Path | None = None
|
|
277
318
|
if flavor is not None:
|
|
278
319
|
font.ttfont.flavor = None
|
|
279
320
|
temp_file = get_temp_file_path()
|
|
280
|
-
|
|
321
|
+
try:
|
|
322
|
+
font.save(temp_file)
|
|
323
|
+
except Exception:
|
|
324
|
+
temp_file.unlink(missing_ok=True)
|
|
325
|
+
raise
|
|
326
|
+
finally:
|
|
327
|
+
font.ttfont.flavor = flavor
|
|
281
328
|
input_file = temp_file
|
|
282
329
|
else:
|
|
283
330
|
input_file = font.file
|
|
@@ -289,22 +336,31 @@ def recalc_stems(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
289
336
|
current_stem_snap_h = font.t_cff_.get_hinting_data().get("StemSnapH", None)
|
|
290
337
|
current_stem_snap_v = font.t_cff_.get_hinting_data().get("StemSnapV", None)
|
|
291
338
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
339
|
+
def to_codepoints(sample: tuple[str, ...]) -> set[int] | None:
|
|
340
|
+
codepoints = {ord(char) for text in sample for char in text}
|
|
341
|
+
return codepoints or None
|
|
342
|
+
|
|
343
|
+
try:
|
|
344
|
+
std_h_w, std_v_w, stem_snap_h, stem_snap_v = get_stems(
|
|
345
|
+
input_file,
|
|
346
|
+
report_all_stems=report_all_stems,
|
|
347
|
+
max_distance=max_distance,
|
|
348
|
+
max_h_stems=max_h_stems,
|
|
349
|
+
max_v_stems=max_v_stems,
|
|
350
|
+
use_samples=use_samples,
|
|
351
|
+
std_h_codepoints=to_codepoints(std_h_sample),
|
|
352
|
+
std_v_codepoints=to_codepoints(std_v_sample),
|
|
353
|
+
snap_h_codepoints=to_codepoints(snap_h_sample),
|
|
354
|
+
snap_v_codepoints=to_codepoints(snap_v_sample),
|
|
355
|
+
)
|
|
356
|
+
finally:
|
|
357
|
+
if temp_file is not None:
|
|
358
|
+
temp_file.unlink(missing_ok=True)
|
|
359
|
+
|
|
303
360
|
logger.info(f"StdHW: {current_std_h_w} -> {std_h_w}")
|
|
304
361
|
logger.info(f"StdVW: {current_std_v_w} -> {std_v_w}")
|
|
305
362
|
logger.info(f"StemSnapH: {current_stem_snap_h} -> {stem_snap_h}")
|
|
306
363
|
logger.info(f"StemSnapV: {current_stem_snap_v} -> {stem_snap_v}")
|
|
307
|
-
temp_file.unlink(missing_ok=True)
|
|
308
364
|
|
|
309
365
|
if (current_std_h_w, current_std_v_w, current_stem_snap_h, current_stem_snap_v) == (
|
|
310
366
|
std_h_w,
|
|
@@ -321,7 +377,6 @@ def recalc_stems(input_path: Path, **options: dict[str, Any]) -> None:
|
|
|
321
377
|
"StemSnapV": stem_snap_v,
|
|
322
378
|
}
|
|
323
379
|
font.t_cff_.set_hinting_data(**hinting_data)
|
|
324
|
-
font.ttfont.flavor = flavor
|
|
325
380
|
return True
|
|
326
381
|
|
|
327
382
|
runner = TaskRunner(input_path=input_path, task=task, **options)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foundrytools-cli
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: A set of command line tools to inspect, manipulate and convert font files
|
|
5
5
|
Author: Cesare Gilento
|
|
6
6
|
Author-email: Cesare Gilento <ftcli@proton.me>
|
|
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.15
|
|
|
19
19
|
Classifier: Topic :: Text Processing :: Fonts
|
|
20
20
|
Requires-Dist: afdko==4.0.3
|
|
21
21
|
Requires-Dist: click>=8.5.0
|
|
22
|
-
Requires-Dist: foundrytools>=0.1.
|
|
22
|
+
Requires-Dist: foundrytools>=0.1.8
|
|
23
23
|
Requires-Dist: loguru>=0.7.3
|
|
24
24
|
Requires-Dist: pathvalidate>=3.3.1
|
|
25
25
|
Requires-Dist: rich>=15.0.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
foundrytools_cli/__init__.py,sha256=
|
|
1
|
+
foundrytools_cli/__init__.py,sha256=sbn6cAzth_0W8DKGXXzEzzbAeIAiO87N0lzpVApo2OY,55
|
|
2
2
|
foundrytools_cli/__main__.py,sha256=wN2lDr2iQyzfnOP00_P3DyXIxEBbf6K_cuzX5YFH5Fg,1273
|
|
3
3
|
foundrytools_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
foundrytools_cli/commands/cff.py,sha256=6eEZydw0ZyISjYuV0JObmNBI7ijdEvVatKwWc8FM5vw,3386
|
|
@@ -10,12 +10,12 @@ foundrytools_cli/commands/fix/__init__.py,sha256=1kJOW26OAkCYYvYDG2H9sCSqqQUQEtw
|
|
|
10
10
|
foundrytools_cli/commands/fix/cli.py,sha256=bcmppksAZ_vkV5ZyHiCw-B3ukEbul20h5i3A5NfcYhA,17578
|
|
11
11
|
foundrytools_cli/commands/fix/legacy_accents.py,sha256=pUHWxV-a2GZgI8W_K2u-lu2yMQt5YKEpQHUD9FyKl8A,2094
|
|
12
12
|
foundrytools_cli/commands/fix/vertical_metrics.py,sha256=j563oWfe3znOKuEW333Yx60d_14Nt0cGdXg3mkCTIN8,691
|
|
13
|
-
foundrytools_cli/commands/font.py,sha256=
|
|
13
|
+
foundrytools_cli/commands/font.py,sha256=WIxz2qqcLloXWxiuvBMp1lAnXyftQ3lLJSKM_3Xhc08,9490
|
|
14
14
|
foundrytools_cli/commands/gsub.py,sha256=iaOAy4jqW6p_RIBxvixtwaEV5AQivaezy0k_Mcufoqg,1454
|
|
15
15
|
foundrytools_cli/commands/hhea.py,sha256=wRld1Cj2q6RnLspMgj_1Z62pIw6Vhqgrm1RO06_qwwc,3158
|
|
16
16
|
foundrytools_cli/commands/name.py,sha256=2EizKjc3puytua2BVnuCcRuP6NzuwNZpZryPZ8uNL-o,10354
|
|
17
17
|
foundrytools_cli/commands/os_2.py,sha256=htdQgD6QLM4v_opVhDtFf9Qhyrz7_gKToQ-xiMHCTCk,19495
|
|
18
|
-
foundrytools_cli/commands/otf.py,sha256=
|
|
18
|
+
foundrytools_cli/commands/otf.py,sha256=cb8lfxXooGs7nXOx2i33MfFYYgU8nVgTH7A20Q3doCM,12543
|
|
19
19
|
foundrytools_cli/commands/post.py,sha256=HpcQD_FKSw8Pr8a6gs62Ln_X9TtqODWHSKNZBmmMT40,2016
|
|
20
20
|
foundrytools_cli/commands/print/__init__.py,sha256=B1h44RtXGw3V4X5se75oCvQPWkh0RbQ0luHxK6z4ge8,71
|
|
21
21
|
foundrytools_cli/commands/print/cli.py,sha256=34CaQIby0u9tZ2vrsKFmvSVg5WH6eEgP5p9FZRoVDEU,1910
|
|
@@ -32,7 +32,7 @@ foundrytools_cli/utils/__init__.py,sha256=m-jBbONfS-_WMbpql8GV_1KufNoWOLQuNQtqEr
|
|
|
32
32
|
foundrytools_cli/utils/logger.py,sha256=ZjVgZ1AmzwwH1GEnBU1HP-pFvZv0BKkVV93P2gYvnLc,525
|
|
33
33
|
foundrytools_cli/utils/task_runner.py,sha256=CXVItMJTslNuie_rhPpZrQBX5rgkWbAWX805dFIBInA,6965
|
|
34
34
|
foundrytools_cli/utils/timer.py,sha256=i_E1nM4KuooZwT2_2bkNJCxLrSKBaQCIMaHxTHY-Hzs,1870
|
|
35
|
-
foundrytools_cli-2.2.
|
|
36
|
-
foundrytools_cli-2.2.
|
|
37
|
-
foundrytools_cli-2.2.
|
|
38
|
-
foundrytools_cli-2.2.
|
|
35
|
+
foundrytools_cli-2.2.1.dist-info/WHEEL,sha256=9IUYslYuG_asT4WlWvfk_K76nveuLvSTKDoLeL0cV-Q,80
|
|
36
|
+
foundrytools_cli-2.2.1.dist-info/entry_points.txt,sha256=sNn6z8yZnx3Koh85LS6BYDqzaXZSP4KEvN3AdFGYRao,57
|
|
37
|
+
foundrytools_cli-2.2.1.dist-info/METADATA,sha256=EX2xD7jjsAqGijDhsEeeyoVqTh7aFpJWQoG9Ckza3ZU,3777
|
|
38
|
+
foundrytools_cli-2.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|