python-fontbro 0.29.0__tar.gz → 0.31.0__tar.gz
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.
- {python_fontbro-0.29.0/python_fontbro.egg-info → python_fontbro-0.31.0}/PKG-INFO +49 -2
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/README.md +48 -1
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/data/features.json +1 -1
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/data/unicode-blocks.json +28 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/data/unicode-scripts.json +32 -17
- python_fontbro-0.31.0/fontbro/features.py +124 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/font.py +59 -1
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/metadata.py +1 -1
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/names.py +253 -17
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/variable.py +32 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0/python_fontbro.egg-info}/PKG-INFO +49 -2
- python_fontbro-0.31.0/tests/test_features.py +149 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_instantiation.py +46 -0
- python_fontbro-0.31.0/tests/test_rename.py +454 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_unicode_blocks_and_scripts.py +16 -16
- python_fontbro-0.29.0/fontbro/features.py +0 -48
- python_fontbro-0.29.0/tests/test_features.py +0 -27
- python_fontbro-0.29.0/tests/test_rename.py +0 -163
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/LICENSE.txt +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/MANIFEST.in +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/__init__.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/bitmap.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/color.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/data/family-classifications.json +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/embedding_permissions.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/exceptions.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/family_classification.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/files.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/fingerprint.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/flags.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/glyphs.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/math.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/metrics.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/monospace.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/pixel.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/py.typed +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/render.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/sanitize.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/style_flags.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/subset.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/support.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/tables.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/unicode.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/utils.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/fontbro/version.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/pyproject.toml +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/python_fontbro.egg-info/SOURCES.txt +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/python_fontbro.egg-info/dependency_links.txt +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/python_fontbro.egg-info/requires.txt +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/python_fontbro.egg-info/top_level.txt +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/setup.cfg +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/setup.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_bitmap.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_characters.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_clone.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_close.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_collection.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_color.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_context_manager.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_embedding_permissions.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_family_classification.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_family_name.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_filename.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_fingerprint.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_format.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_glyphs.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_image.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_init.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_issues.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_italic_angle.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_monospace.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_names.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_pixel.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_sanitize.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_save.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_str.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_style_flags.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_style_name.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_subset.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_support.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_svg.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_tables.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_unicode.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_update_unicode_data.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_variable.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_version.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_vertical_metrics.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_weight.py +0 -0
- {python_fontbro-0.29.0 → python_fontbro-0.31.0}/tests/test_width.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-fontbro
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.31.0
|
|
4
4
|
Summary: friendly font operations on top of fontTools.
|
|
5
5
|
Author-email: Fabio Caccamo <fabio.caccamo@gmail.com>
|
|
6
6
|
Maintainer-email: Fabio Caccamo <fabio.caccamo@gmail.com>
|
|
@@ -149,6 +149,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
149
149
|
- [`is_static`](#is_static)
|
|
150
150
|
- [`is_variable`](#is_variable)
|
|
151
151
|
- [`rename`](#rename)
|
|
152
|
+
- [`rename_variable_instances`](#rename_variable_instances)
|
|
152
153
|
- [`sanitize`](#sanitize)
|
|
153
154
|
- [`save`](#save)
|
|
154
155
|
- [`save_as_woff`](#save_as_woff)
|
|
@@ -966,6 +967,8 @@ variable = font.is_variable()
|
|
|
966
967
|
"""
|
|
967
968
|
Renames the font names records (1, 2, 4, 6, 16, 17) according to
|
|
968
969
|
the given family_name and style_name (subfamily_name).
|
|
970
|
+
The names records (18, 25), the fvar named instances PostScript names
|
|
971
|
+
and the CFF table names are updated too, only if already defined.
|
|
969
972
|
|
|
970
973
|
If family_name is not defined it will be auto-detected.
|
|
971
974
|
If style_name is not defined it will be auto-detected.
|
|
@@ -985,6 +988,39 @@ font.rename(
|
|
|
985
988
|
)
|
|
986
989
|
```
|
|
987
990
|
|
|
991
|
+
#### `rename_variable_instances`
|
|
992
|
+
```python
|
|
993
|
+
"""
|
|
994
|
+
Renames the named instances of the variable font.
|
|
995
|
+
|
|
996
|
+
The family_name replaces the family part of the instances PostScript names
|
|
997
|
+
(and of the variations PostScript name prefix, if defined).
|
|
998
|
+
The style_names replace the instances style names and the style part
|
|
999
|
+
of their PostScript names. The axes names are unchanged.
|
|
1000
|
+
The default instance style name must match the font style name,
|
|
1001
|
+
so renaming it renames the font style too.
|
|
1002
|
+
|
|
1003
|
+
If family_name is not defined it will be auto-detected.
|
|
1004
|
+
|
|
1005
|
+
:param family_name: The family name
|
|
1006
|
+
:type family_name: str
|
|
1007
|
+
:param style_names: The new style names mapped by the old ones (case-insensitive),
|
|
1008
|
+
eg. {"Thin": "Hairline"}
|
|
1009
|
+
:type style_names: dict or None
|
|
1010
|
+
:param update_style_flags: if True the style flags will be updated by subfamily name
|
|
1011
|
+
(only if the default instance style name is renamed)
|
|
1012
|
+
:type update_style_flags: bool
|
|
1013
|
+
|
|
1014
|
+
:raises OperationError: if the font is not a variable font.
|
|
1015
|
+
"""
|
|
1016
|
+
|
|
1017
|
+
font.rename_variable_instances(
|
|
1018
|
+
family_name="My Font New",
|
|
1019
|
+
style_names={"Thin": "Hairline"},
|
|
1020
|
+
update_style_flags=True,
|
|
1021
|
+
)
|
|
1022
|
+
```
|
|
1023
|
+
|
|
988
1024
|
#### `sanitize`
|
|
989
1025
|
```python
|
|
990
1026
|
"""
|
|
@@ -1360,6 +1396,12 @@ If an axis min and max values are equal, the axis will be pinned.
|
|
|
1360
1396
|
{'wdth':100, 'wght':[100,600], 'ital':[30,65,70]} or
|
|
1361
1397
|
{'wdth':100, 'wght':{'min':100,'max':600}, 'ital':{'min':30,'default':65,'max':70}}
|
|
1362
1398
|
:type coordinates: dict
|
|
1399
|
+
:param update_names: if True the name records will be updated based on
|
|
1400
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1401
|
+
:type update_names: bool
|
|
1402
|
+
:param update_style_flags: if True the style flags will be updated based on
|
|
1403
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1404
|
+
:type update_style_flags: bool
|
|
1363
1405
|
:param options: The options for the fontTools.varLib.instancer
|
|
1364
1406
|
:type options: dictionary
|
|
1365
1407
|
|
|
@@ -1368,7 +1410,12 @@ If an axis min and max values are equal, the axis will be pinned.
|
|
|
1368
1410
|
:raises ValueError: If the coordinates axes are all pinned
|
|
1369
1411
|
"""
|
|
1370
1412
|
|
|
1371
|
-
font.to_sliced_variable(
|
|
1413
|
+
font.to_sliced_variable(
|
|
1414
|
+
coordinates,
|
|
1415
|
+
update_names=True,
|
|
1416
|
+
update_style_flags=True,
|
|
1417
|
+
**options,
|
|
1418
|
+
)
|
|
1372
1419
|
```
|
|
1373
1420
|
|
|
1374
1421
|
#### `to_static`
|
|
@@ -85,6 +85,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
85
85
|
- [`is_static`](#is_static)
|
|
86
86
|
- [`is_variable`](#is_variable)
|
|
87
87
|
- [`rename`](#rename)
|
|
88
|
+
- [`rename_variable_instances`](#rename_variable_instances)
|
|
88
89
|
- [`sanitize`](#sanitize)
|
|
89
90
|
- [`save`](#save)
|
|
90
91
|
- [`save_as_woff`](#save_as_woff)
|
|
@@ -902,6 +903,8 @@ variable = font.is_variable()
|
|
|
902
903
|
"""
|
|
903
904
|
Renames the font names records (1, 2, 4, 6, 16, 17) according to
|
|
904
905
|
the given family_name and style_name (subfamily_name).
|
|
906
|
+
The names records (18, 25), the fvar named instances PostScript names
|
|
907
|
+
and the CFF table names are updated too, only if already defined.
|
|
905
908
|
|
|
906
909
|
If family_name is not defined it will be auto-detected.
|
|
907
910
|
If style_name is not defined it will be auto-detected.
|
|
@@ -921,6 +924,39 @@ font.rename(
|
|
|
921
924
|
)
|
|
922
925
|
```
|
|
923
926
|
|
|
927
|
+
#### `rename_variable_instances`
|
|
928
|
+
```python
|
|
929
|
+
"""
|
|
930
|
+
Renames the named instances of the variable font.
|
|
931
|
+
|
|
932
|
+
The family_name replaces the family part of the instances PostScript names
|
|
933
|
+
(and of the variations PostScript name prefix, if defined).
|
|
934
|
+
The style_names replace the instances style names and the style part
|
|
935
|
+
of their PostScript names. The axes names are unchanged.
|
|
936
|
+
The default instance style name must match the font style name,
|
|
937
|
+
so renaming it renames the font style too.
|
|
938
|
+
|
|
939
|
+
If family_name is not defined it will be auto-detected.
|
|
940
|
+
|
|
941
|
+
:param family_name: The family name
|
|
942
|
+
:type family_name: str
|
|
943
|
+
:param style_names: The new style names mapped by the old ones (case-insensitive),
|
|
944
|
+
eg. {"Thin": "Hairline"}
|
|
945
|
+
:type style_names: dict or None
|
|
946
|
+
:param update_style_flags: if True the style flags will be updated by subfamily name
|
|
947
|
+
(only if the default instance style name is renamed)
|
|
948
|
+
:type update_style_flags: bool
|
|
949
|
+
|
|
950
|
+
:raises OperationError: if the font is not a variable font.
|
|
951
|
+
"""
|
|
952
|
+
|
|
953
|
+
font.rename_variable_instances(
|
|
954
|
+
family_name="My Font New",
|
|
955
|
+
style_names={"Thin": "Hairline"},
|
|
956
|
+
update_style_flags=True,
|
|
957
|
+
)
|
|
958
|
+
```
|
|
959
|
+
|
|
924
960
|
#### `sanitize`
|
|
925
961
|
```python
|
|
926
962
|
"""
|
|
@@ -1296,6 +1332,12 @@ If an axis min and max values are equal, the axis will be pinned.
|
|
|
1296
1332
|
{'wdth':100, 'wght':[100,600], 'ital':[30,65,70]} or
|
|
1297
1333
|
{'wdth':100, 'wght':{'min':100,'max':600}, 'ital':{'min':30,'default':65,'max':70}}
|
|
1298
1334
|
:type coordinates: dict
|
|
1335
|
+
:param update_names: if True the name records will be updated based on
|
|
1336
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1337
|
+
:type update_names: bool
|
|
1338
|
+
:param update_style_flags: if True the style flags will be updated based on
|
|
1339
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1340
|
+
:type update_style_flags: bool
|
|
1299
1341
|
:param options: The options for the fontTools.varLib.instancer
|
|
1300
1342
|
:type options: dictionary
|
|
1301
1343
|
|
|
@@ -1304,7 +1346,12 @@ If an axis min and max values are equal, the axis will be pinned.
|
|
|
1304
1346
|
:raises ValueError: If the coordinates axes are all pinned
|
|
1305
1347
|
"""
|
|
1306
1348
|
|
|
1307
|
-
font.to_sliced_variable(
|
|
1349
|
+
font.to_sliced_variable(
|
|
1350
|
+
coordinates,
|
|
1351
|
+
update_names=True,
|
|
1352
|
+
update_style_flags=True,
|
|
1353
|
+
**options,
|
|
1354
|
+
)
|
|
1308
1355
|
```
|
|
1309
1356
|
|
|
1310
1357
|
#### `to_static`
|
|
@@ -1015,6 +1015,10 @@
|
|
|
1015
1015
|
"characters_total": 64,
|
|
1016
1016
|
"name": "Tolong Siki"
|
|
1017
1017
|
},
|
|
1018
|
+
{
|
|
1019
|
+
"characters_total": 16,
|
|
1020
|
+
"name": "Bengali Supplement"
|
|
1021
|
+
},
|
|
1018
1022
|
{
|
|
1019
1023
|
"characters_total": 32,
|
|
1020
1024
|
"name": "Makasar"
|
|
@@ -1043,6 +1047,10 @@
|
|
|
1043
1047
|
"characters_total": 208,
|
|
1044
1048
|
"name": "Early Dynastic Cuneiform"
|
|
1045
1049
|
},
|
|
1050
|
+
{
|
|
1051
|
+
"characters_total": 320,
|
|
1052
|
+
"name": "Archaic Cuneiform Numerals"
|
|
1053
|
+
},
|
|
1046
1054
|
{
|
|
1047
1055
|
"characters_total": 112,
|
|
1048
1056
|
"name": "Cypro-Minoan"
|
|
@@ -1127,6 +1135,14 @@
|
|
|
1127
1135
|
"characters_total": 128,
|
|
1128
1136
|
"name": "Tangut Components Supplement"
|
|
1129
1137
|
},
|
|
1138
|
+
{
|
|
1139
|
+
"characters_total": 928,
|
|
1140
|
+
"name": "Jurchen"
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
"characters_total": 64,
|
|
1144
|
+
"name": "Jurchen Radicals"
|
|
1145
|
+
},
|
|
1130
1146
|
{
|
|
1131
1147
|
"characters_total": 16,
|
|
1132
1148
|
"name": "Kana Extended-B"
|
|
@@ -1179,6 +1195,10 @@
|
|
|
1179
1195
|
"characters_total": 80,
|
|
1180
1196
|
"name": "Ancient Greek Musical Notation"
|
|
1181
1197
|
},
|
|
1198
|
+
{
|
|
1199
|
+
"characters_total": 64,
|
|
1200
|
+
"name": "Musical Symbols Supplement"
|
|
1201
|
+
},
|
|
1182
1202
|
{
|
|
1183
1203
|
"characters_total": 32,
|
|
1184
1204
|
"name": "Kaktovik Numerals"
|
|
@@ -1203,6 +1223,10 @@
|
|
|
1203
1223
|
"characters_total": 688,
|
|
1204
1224
|
"name": "Sutton SignWriting"
|
|
1205
1225
|
},
|
|
1226
|
+
{
|
|
1227
|
+
"characters_total": 256,
|
|
1228
|
+
"name": "Miscellaneous Symbols and Arrows Extended"
|
|
1229
|
+
},
|
|
1206
1230
|
{
|
|
1207
1231
|
"characters_total": 256,
|
|
1208
1232
|
"name": "Latin Extended-G"
|
|
@@ -1367,6 +1391,10 @@
|
|
|
1367
1391
|
"characters_total": 4304,
|
|
1368
1392
|
"name": "CJK Unified Ideographs Extension J"
|
|
1369
1393
|
},
|
|
1394
|
+
{
|
|
1395
|
+
"characters_total": 11328,
|
|
1396
|
+
"name": "Seal"
|
|
1397
|
+
},
|
|
1370
1398
|
{
|
|
1371
1399
|
"characters_total": 128,
|
|
1372
1400
|
"name": "Tags"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"characters_total":
|
|
3
|
+
"characters_total": 9276,
|
|
4
4
|
"name": "Common",
|
|
5
5
|
"tag": "Zyyy"
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
|
-
"characters_total":
|
|
8
|
+
"characters_total": 1653,
|
|
9
9
|
"name": "Latin",
|
|
10
10
|
"tag": "Latn"
|
|
11
11
|
},
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
"tag": "Bopo"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"characters_total":
|
|
18
|
+
"characters_total": 695,
|
|
19
19
|
"name": "Inherited",
|
|
20
20
|
"tag": "Zinh"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
"characters_total":
|
|
23
|
+
"characters_total": 520,
|
|
24
24
|
"name": "Greek",
|
|
25
25
|
"tag": "Grek"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
|
-
"characters_total":
|
|
28
|
+
"characters_total": 143911,
|
|
29
29
|
"name": "Unknown",
|
|
30
30
|
"tag": "Zzzz"
|
|
31
31
|
},
|
|
@@ -40,17 +40,17 @@
|
|
|
40
40
|
"tag": "Cyrl"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
"characters_total":
|
|
43
|
+
"characters_total": 99,
|
|
44
44
|
"name": "Armenian",
|
|
45
45
|
"tag": "Armn"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
"characters_total":
|
|
48
|
+
"characters_total": 136,
|
|
49
49
|
"name": "Hebrew",
|
|
50
50
|
"tag": "Hebr"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
|
-
"characters_total":
|
|
53
|
+
"characters_total": 1452,
|
|
54
54
|
"name": "Arabic",
|
|
55
55
|
"tag": "Arab"
|
|
56
56
|
},
|
|
@@ -80,12 +80,12 @@
|
|
|
80
80
|
"tag": "Mand"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
|
-
"characters_total":
|
|
83
|
+
"characters_total": 165,
|
|
84
84
|
"name": "Devanagari",
|
|
85
85
|
"tag": "Deva"
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
|
-
"characters_total":
|
|
88
|
+
"characters_total": 98,
|
|
89
89
|
"name": "Bengali",
|
|
90
90
|
"tag": "Beng"
|
|
91
91
|
},
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"tag": "Gujr"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
|
-
"characters_total":
|
|
103
|
+
"characters_total": 93,
|
|
104
104
|
"name": "Oriya",
|
|
105
105
|
"tag": "Orya"
|
|
106
106
|
},
|
|
@@ -280,17 +280,17 @@
|
|
|
280
280
|
"tag": "Tfng"
|
|
281
281
|
},
|
|
282
282
|
{
|
|
283
|
-
"characters_total":
|
|
283
|
+
"characters_total": 103352,
|
|
284
284
|
"name": "Han",
|
|
285
285
|
"tag": "Hani"
|
|
286
286
|
},
|
|
287
287
|
{
|
|
288
|
-
"characters_total":
|
|
288
|
+
"characters_total": 382,
|
|
289
289
|
"name": "Hiragana",
|
|
290
290
|
"tag": "Hira"
|
|
291
291
|
},
|
|
292
292
|
{
|
|
293
|
-
"characters_total":
|
|
293
|
+
"characters_total": 327,
|
|
294
294
|
"name": "Katakana",
|
|
295
295
|
"tag": "Kana"
|
|
296
296
|
},
|
|
@@ -745,10 +745,15 @@
|
|
|
745
745
|
"tag": "Kawi"
|
|
746
746
|
},
|
|
747
747
|
{
|
|
748
|
-
"characters_total":
|
|
748
|
+
"characters_total": 1393,
|
|
749
749
|
"name": "Cuneiform",
|
|
750
750
|
"tag": "Xsux"
|
|
751
751
|
},
|
|
752
|
+
{
|
|
753
|
+
"characters_total": 164,
|
|
754
|
+
"name": "Proto Cuneiform",
|
|
755
|
+
"tag": "Pcun"
|
|
756
|
+
},
|
|
752
757
|
{
|
|
753
758
|
"characters_total": 99,
|
|
754
759
|
"name": "Cypro Minoan",
|
|
@@ -810,7 +815,7 @@
|
|
|
810
815
|
"tag": "Plrd"
|
|
811
816
|
},
|
|
812
817
|
{
|
|
813
|
-
"characters_total":
|
|
818
|
+
"characters_total": 7061,
|
|
814
819
|
"name": "Tangut",
|
|
815
820
|
"tag": "Tang"
|
|
816
821
|
},
|
|
@@ -820,10 +825,15 @@
|
|
|
820
825
|
"tag": "Nshu"
|
|
821
826
|
},
|
|
822
827
|
{
|
|
823
|
-
"characters_total":
|
|
828
|
+
"characters_total": 477,
|
|
824
829
|
"name": "Khitan Small Script",
|
|
825
830
|
"tag": "Kits"
|
|
826
831
|
},
|
|
832
|
+
{
|
|
833
|
+
"characters_total": 965,
|
|
834
|
+
"name": "Jurchen",
|
|
835
|
+
"tag": "Jurc"
|
|
836
|
+
},
|
|
827
837
|
{
|
|
828
838
|
"characters_total": 143,
|
|
829
839
|
"name": "Duployan",
|
|
@@ -873,5 +883,10 @@
|
|
|
873
883
|
"characters_total": 88,
|
|
874
884
|
"name": "Adlam",
|
|
875
885
|
"tag": "Adlm"
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
"characters_total": 11328,
|
|
889
|
+
"name": "Seal",
|
|
890
|
+
"tag": "Seal"
|
|
876
891
|
}
|
|
877
892
|
]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from fontTools.ttLib import TTFont
|
|
6
|
+
|
|
7
|
+
from fontbro.utils import read_json
|
|
8
|
+
|
|
9
|
+
# Features:
|
|
10
|
+
# https://docs.microsoft.com/en-gb/typography/opentype/spec/featurelist
|
|
11
|
+
# https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings
|
|
12
|
+
_FEATURES_LIST: list[dict[str, Any]] = read_json("data/features.json")
|
|
13
|
+
_FEATURES_BY_TAG: dict[str, dict[str, Any]] = {
|
|
14
|
+
feature["tag"]: feature for feature in _FEATURES_LIST
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_features(
|
|
19
|
+
ttfont: TTFont,
|
|
20
|
+
) -> list[dict[str, Any]]:
|
|
21
|
+
"""
|
|
22
|
+
Gets the opentype features of the given font.
|
|
23
|
+
"""
|
|
24
|
+
features_tags = get_features_tags(ttfont)
|
|
25
|
+
features_params = _get_features_params(ttfont)
|
|
26
|
+
features = []
|
|
27
|
+
for features_tag in features_tags:
|
|
28
|
+
if features_tag not in _FEATURES_BY_TAG:
|
|
29
|
+
continue
|
|
30
|
+
feature = _FEATURES_BY_TAG[features_tag].copy()
|
|
31
|
+
feature["params"] = _get_feature_params_dict(
|
|
32
|
+
ttfont, features_params.get(features_tag)
|
|
33
|
+
)
|
|
34
|
+
features.append(feature)
|
|
35
|
+
return features
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _get_features_params(
|
|
39
|
+
ttfont: TTFont,
|
|
40
|
+
) -> dict[str, Any]:
|
|
41
|
+
"""
|
|
42
|
+
Gets the opentype features params (if any) of the given font by tag.
|
|
43
|
+
"""
|
|
44
|
+
features_params: dict[str, Any] = {}
|
|
45
|
+
for table_tag in ["GPOS", "GSUB"]:
|
|
46
|
+
if table_tag in ttfont:
|
|
47
|
+
table = ttfont[table_tag].table
|
|
48
|
+
try:
|
|
49
|
+
feature_record = table.FeatureList.FeatureRecord or []
|
|
50
|
+
except AttributeError:
|
|
51
|
+
feature_record = []
|
|
52
|
+
for feature in feature_record:
|
|
53
|
+
feature_params = feature.Feature.FeatureParams
|
|
54
|
+
if feature_params is not None:
|
|
55
|
+
features_params.setdefault(feature.FeatureTag, feature_params)
|
|
56
|
+
return features_params
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _get_feature_params_dict(
|
|
60
|
+
ttfont: TTFont,
|
|
61
|
+
feature_params: Any,
|
|
62
|
+
) -> dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Gets the designer-defined params of a feature:
|
|
65
|
+
stylistic sets (ss01-ss20) and character variants (cv01-cv99).
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def get_name(name_id: int | None) -> str | None:
|
|
69
|
+
if not name_id or "name" not in ttfont:
|
|
70
|
+
return None
|
|
71
|
+
name: str | None = ttfont["name"].getDebugName(name_id)
|
|
72
|
+
return name
|
|
73
|
+
|
|
74
|
+
params: dict[str, Any] = {
|
|
75
|
+
"name": None,
|
|
76
|
+
"tooltip": None,
|
|
77
|
+
"sample_text": None,
|
|
78
|
+
"labels": [],
|
|
79
|
+
"characters": [],
|
|
80
|
+
}
|
|
81
|
+
if feature_params is None:
|
|
82
|
+
return params
|
|
83
|
+
params["name"] = get_name(
|
|
84
|
+
getattr(feature_params, "UINameID", None)
|
|
85
|
+
or getattr(feature_params, "FeatUILabelNameID", None)
|
|
86
|
+
)
|
|
87
|
+
params["tooltip"] = get_name(
|
|
88
|
+
getattr(feature_params, "FeatUITooltipTextNameID", None)
|
|
89
|
+
)
|
|
90
|
+
params["sample_text"] = get_name(getattr(feature_params, "SampleTextNameID", None))
|
|
91
|
+
first_label_name_id = getattr(feature_params, "FirstParamUILabelNameID", 0)
|
|
92
|
+
labels_count = getattr(feature_params, "NumNamedParameters", 0)
|
|
93
|
+
if first_label_name_id:
|
|
94
|
+
# keep missing labels as None to preserve the label index / feature value match
|
|
95
|
+
params["labels"] = [
|
|
96
|
+
get_name(first_label_name_id + index) for index in range(labels_count)
|
|
97
|
+
]
|
|
98
|
+
# characters are stored as uint24, skip values that are not unicode scalar values
|
|
99
|
+
characters = getattr(feature_params, "Character", None) or []
|
|
100
|
+
params["characters"] = [
|
|
101
|
+
chr(character)
|
|
102
|
+
for character in characters
|
|
103
|
+
if 0 <= character <= 0x10FFFF and not 0xD800 <= character <= 0xDFFF
|
|
104
|
+
]
|
|
105
|
+
return params
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_features_tags(
|
|
109
|
+
ttfont: TTFont,
|
|
110
|
+
) -> list[str]:
|
|
111
|
+
"""
|
|
112
|
+
Gets the opentype features tags of the given font.
|
|
113
|
+
"""
|
|
114
|
+
features_tags = set()
|
|
115
|
+
for table_tag in ["GPOS", "GSUB"]:
|
|
116
|
+
if table_tag in ttfont:
|
|
117
|
+
table = ttfont[table_tag].table
|
|
118
|
+
try:
|
|
119
|
+
feature_record = table.FeatureList.FeatureRecord or []
|
|
120
|
+
except AttributeError:
|
|
121
|
+
feature_record = []
|
|
122
|
+
for feature in feature_record:
|
|
123
|
+
features_tags.add(feature.FeatureTag)
|
|
124
|
+
return sorted(features_tags)
|
|
@@ -1227,6 +1227,8 @@ class Font:
|
|
|
1227
1227
|
"""
|
|
1228
1228
|
Renames the font names records (1, 2, 4, 6, 16, 17) according to
|
|
1229
1229
|
the given family_name and style_name (subfamily_name).
|
|
1230
|
+
The names records (18, 25), the fvar named instances PostScript names
|
|
1231
|
+
and the CFF table names are updated too, only if already defined.
|
|
1230
1232
|
|
|
1231
1233
|
If family_name is not defined it will be auto-detected.
|
|
1232
1234
|
If style_name is not defined it will be auto-detected.
|
|
@@ -1247,6 +1249,48 @@ class Font:
|
|
|
1247
1249
|
if update_style_flags:
|
|
1248
1250
|
self.set_style_flags_by_subfamily_name()
|
|
1249
1251
|
|
|
1252
|
+
def rename_variable_instances(
|
|
1253
|
+
self,
|
|
1254
|
+
*,
|
|
1255
|
+
family_name: str = "",
|
|
1256
|
+
style_names: dict[str, str] | None = None,
|
|
1257
|
+
update_style_flags: bool = True,
|
|
1258
|
+
) -> None:
|
|
1259
|
+
"""
|
|
1260
|
+
Renames the named instances of the variable font.
|
|
1261
|
+
|
|
1262
|
+
The family_name replaces the family part of the instances PostScript names
|
|
1263
|
+
(and of the variations PostScript name prefix, if defined).
|
|
1264
|
+
The style_names replace the instances style names and the style part
|
|
1265
|
+
of their PostScript names. The axes names are unchanged.
|
|
1266
|
+
The default instance style name must match the font style name,
|
|
1267
|
+
so renaming it renames the font style too.
|
|
1268
|
+
|
|
1269
|
+
If family_name is not defined it will be auto-detected.
|
|
1270
|
+
|
|
1271
|
+
:param family_name: The family name
|
|
1272
|
+
:type family_name: str
|
|
1273
|
+
:param style_names: The new style names mapped by the old ones (case-insensitive),
|
|
1274
|
+
eg. {"Thin": "Hairline"}
|
|
1275
|
+
:type style_names: dict or None
|
|
1276
|
+
:param update_style_flags: if True the style flags will be updated by subfamily name
|
|
1277
|
+
(only if the default instance style name is renamed)
|
|
1278
|
+
:type update_style_flags: bool
|
|
1279
|
+
|
|
1280
|
+
:raises OperationError: if the font is not a variable font.
|
|
1281
|
+
:return: None
|
|
1282
|
+
"""
|
|
1283
|
+
ttfont = self.get_ttfont()
|
|
1284
|
+
style_name = self.get_style_name()
|
|
1285
|
+
_names.rename_variable_instances(
|
|
1286
|
+
ttfont,
|
|
1287
|
+
family_name=family_name,
|
|
1288
|
+
style_names=style_names,
|
|
1289
|
+
)
|
|
1290
|
+
|
|
1291
|
+
if update_style_flags and self.get_style_name() != style_name:
|
|
1292
|
+
self.set_style_flags_by_subfamily_name()
|
|
1293
|
+
|
|
1250
1294
|
def sanitize(
|
|
1251
1295
|
self,
|
|
1252
1296
|
*,
|
|
@@ -1791,6 +1835,8 @@ class Font:
|
|
|
1791
1835
|
self,
|
|
1792
1836
|
*,
|
|
1793
1837
|
coordinates: dict[str, Any],
|
|
1838
|
+
update_names: bool = True,
|
|
1839
|
+
update_style_flags: bool = True,
|
|
1794
1840
|
**options: Any,
|
|
1795
1841
|
) -> None:
|
|
1796
1842
|
"""
|
|
@@ -1805,6 +1851,12 @@ class Font:
|
|
|
1805
1851
|
{'wdth':100, 'wght':[100,600], 'ital':[30,65,70]} or
|
|
1806
1852
|
{'wdth':100, 'wght':{'min':100,'max':600}, 'ital':{'min':30,'default':65,'max':70}}
|
|
1807
1853
|
:type coordinates: dict
|
|
1854
|
+
:param update_names: if True the name records will be updated based on
|
|
1855
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1856
|
+
:type update_names: bool
|
|
1857
|
+
:param update_style_flags: if True the style flags will be updated based on
|
|
1858
|
+
the closest instance to the new default coordinates (only if changed)
|
|
1859
|
+
:type update_style_flags: bool
|
|
1808
1860
|
:param options: The options for the fontTools.varLib.instancer
|
|
1809
1861
|
:type options: dictionary
|
|
1810
1862
|
|
|
@@ -1813,7 +1865,13 @@ class Font:
|
|
|
1813
1865
|
:raises ValueError: If the coordinates axes are all pinned
|
|
1814
1866
|
"""
|
|
1815
1867
|
ttfont = self.get_ttfont()
|
|
1816
|
-
_variable.to_sliced_variable(
|
|
1868
|
+
_variable.to_sliced_variable(
|
|
1869
|
+
ttfont,
|
|
1870
|
+
coordinates=coordinates,
|
|
1871
|
+
update_names=update_names,
|
|
1872
|
+
update_style_flags=update_style_flags,
|
|
1873
|
+
**options,
|
|
1874
|
+
)
|
|
1817
1875
|
|
|
1818
1876
|
def to_static(
|
|
1819
1877
|
self,
|