python-fontbro 0.28.1__tar.gz → 0.30.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.28.1/python_fontbro.egg-info → python_fontbro-0.30.0}/PKG-INFO +63 -4
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/README.md +62 -3
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/data/features.json +1 -1
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/data/unicode-blocks.json +28 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/data/unicode-scripts.json +32 -17
- python_fontbro-0.30.0/fontbro/features.py +124 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/files.py +0 -11
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/font.py +74 -3
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/metadata.py +1 -1
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/names.py +46 -13
- python_fontbro-0.30.0/fontbro/version.py +253 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0/python_fontbro.egg-info}/PKG-INFO +63 -4
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/python_fontbro.egg-info/SOURCES.txt +1 -0
- python_fontbro-0.30.0/tests/test_features.py +149 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_names.py +93 -0
- python_fontbro-0.30.0/tests/test_version.py +409 -0
- python_fontbro-0.28.1/fontbro/features.py +0 -48
- python_fontbro-0.28.1/tests/test_features.py +0 -27
- python_fontbro-0.28.1/tests/test_version.py +0 -35
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/LICENSE.txt +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/MANIFEST.in +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/__init__.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/bitmap.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/color.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/data/family-classifications.json +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/embedding_permissions.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/exceptions.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/family_classification.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/fingerprint.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/flags.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/glyphs.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/math.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/metrics.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/monospace.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/pixel.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/py.typed +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/render.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/sanitize.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/style_flags.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/subset.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/support.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/tables.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/unicode.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/utils.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/fontbro/variable.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/pyproject.toml +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/python_fontbro.egg-info/dependency_links.txt +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/python_fontbro.egg-info/requires.txt +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/python_fontbro.egg-info/top_level.txt +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/setup.cfg +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/setup.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_bitmap.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_characters.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_clone.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_close.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_collection.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_color.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_context_manager.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_embedding_permissions.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_family_classification.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_family_name.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_filename.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_fingerprint.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_format.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_glyphs.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_image.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_init.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_instantiation.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_issues.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_italic_angle.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_monospace.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_pixel.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_rename.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_sanitize.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_save.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_str.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_style_flags.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_style_name.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_subset.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_support.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_svg.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_tables.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_unicode.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_unicode_blocks_and_scripts.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_update_unicode_data.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_variable.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_vertical_metrics.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.0}/tests/test_weight.py +0 -0
- {python_fontbro-0.28.1 → python_fontbro-0.30.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.30.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>
|
|
@@ -138,6 +138,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
138
138
|
- [`get_variable_instance_by_style_name`](#get_variable_instance_by_style_name)
|
|
139
139
|
- [`get_variable_instance_closest_to_coordinates`](#get_variable_instance_closest_to_coordinates)
|
|
140
140
|
- [`get_version`](#get_version)
|
|
141
|
+
- [`get_version_formatted`](#get_version_formatted)
|
|
141
142
|
- [`get_vertical_metrics`](#get_vertical_metrics)
|
|
142
143
|
- [`get_weight`](#get_weight)
|
|
143
144
|
- [`get_width`](#get_width)
|
|
@@ -163,6 +164,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
163
164
|
- [`set_style_flags`](#set_style_flags)
|
|
164
165
|
- [`set_style_flags_by_subfamily_name`](#set_style_flags_by_subfamily_name)
|
|
165
166
|
- [`set_style_name`](#set_style_name)
|
|
167
|
+
- [`set_version`](#set_version)
|
|
166
168
|
- [`set_vertical_metrics`](#set_vertical_metrics)
|
|
167
169
|
- [`subset`](#subset)
|
|
168
170
|
- [`to_sliced_variable`](#to_sliced_variable)
|
|
@@ -784,13 +786,48 @@ instance = font.get_variable_instance_closest_to_coordinates(
|
|
|
784
786
|
#### `get_version`
|
|
785
787
|
```python
|
|
786
788
|
"""
|
|
787
|
-
Gets the font version.
|
|
789
|
+
Gets the font version reading it from head.fontRevision,
|
|
790
|
+
with fallback on the version name record (name id 5) parsed value,
|
|
791
|
+
eg. "Version 1.015;git-0a5106e0b" -> 1.015.
|
|
788
792
|
|
|
789
|
-
:
|
|
793
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
794
|
+
:type use_head_revision: bool
|
|
795
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
796
|
+
:type use_name_record: bool
|
|
797
|
+
|
|
798
|
+
:returns: The font version value, 0.0 if the version cannot be read.
|
|
790
799
|
:rtype: float
|
|
800
|
+
|
|
801
|
+
:raises ArgumentError: If both options are False.
|
|
791
802
|
"""
|
|
792
803
|
|
|
793
|
-
version = font.get_version()
|
|
804
|
+
version = font.get_version(use_head_revision=True, use_name_record=True)
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
#### `get_version_formatted`
|
|
808
|
+
```python
|
|
809
|
+
"""
|
|
810
|
+
Gets the font version formatted using the version name record convention,
|
|
811
|
+
with the given prefix and a minimum of 3 decimal digits, eg. "v1.015".
|
|
812
|
+
|
|
813
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
814
|
+
:type use_head_revision: bool
|
|
815
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
816
|
+
:type use_name_record: bool
|
|
817
|
+
:param prefix: The prefix to prepend to the version value.
|
|
818
|
+
:type prefix: str
|
|
819
|
+
|
|
820
|
+
:returns: The formatted font version value, eg. "v0.000" if the version cannot be read.
|
|
821
|
+
:rtype: str
|
|
822
|
+
|
|
823
|
+
:raises ArgumentError: If both source options are False.
|
|
824
|
+
"""
|
|
825
|
+
|
|
826
|
+
version = font.get_version_formatted(
|
|
827
|
+
use_head_revision=True,
|
|
828
|
+
use_name_record=True,
|
|
829
|
+
prefix="v",
|
|
830
|
+
)
|
|
794
831
|
```
|
|
795
832
|
|
|
796
833
|
#### `get_vertical_metrics`
|
|
@@ -1240,6 +1277,28 @@ Sets the style name updating the related font names records.
|
|
|
1240
1277
|
font.set_style_name(name="Bold Italic")
|
|
1241
1278
|
```
|
|
1242
1279
|
|
|
1280
|
+
#### `set_version`
|
|
1281
|
+
```python
|
|
1282
|
+
"""
|
|
1283
|
+
Sets the font version, the version value can be a number (eg. 1.015)
|
|
1284
|
+
or a version string (eg. "Version 1.015"), parsed the same way the
|
|
1285
|
+
version name record value is parsed when read.
|
|
1286
|
+
The head.fontRevision and the version name record (name id 5) are
|
|
1287
|
+
updated, the latter is overwritten with the canonical "Version X.YYY"
|
|
1288
|
+
form (any extra info it contained is dropped).
|
|
1289
|
+
The unique identifier name record (name id 3) is updated only if its
|
|
1290
|
+
first ";" separated part holds the current version value, and only in
|
|
1291
|
+
that part. The CFF version is updated only if the font already has it.
|
|
1292
|
+
|
|
1293
|
+
:param version: The version value, eg. 1.015 or "Version 1.015"
|
|
1294
|
+
:type version: float or str
|
|
1295
|
+
|
|
1296
|
+
:raises ArgumentError: If the version value is not valid.
|
|
1297
|
+
"""
|
|
1298
|
+
|
|
1299
|
+
font.set_version(1.015)
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1243
1302
|
#### `set_vertical_metrics`
|
|
1244
1303
|
```python
|
|
1245
1304
|
"""
|
|
@@ -74,6 +74,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
74
74
|
- [`get_variable_instance_by_style_name`](#get_variable_instance_by_style_name)
|
|
75
75
|
- [`get_variable_instance_closest_to_coordinates`](#get_variable_instance_closest_to_coordinates)
|
|
76
76
|
- [`get_version`](#get_version)
|
|
77
|
+
- [`get_version_formatted`](#get_version_formatted)
|
|
77
78
|
- [`get_vertical_metrics`](#get_vertical_metrics)
|
|
78
79
|
- [`get_weight`](#get_weight)
|
|
79
80
|
- [`get_width`](#get_width)
|
|
@@ -99,6 +100,7 @@ with open("fonts/MyFont.ttf") as fh:
|
|
|
99
100
|
- [`set_style_flags`](#set_style_flags)
|
|
100
101
|
- [`set_style_flags_by_subfamily_name`](#set_style_flags_by_subfamily_name)
|
|
101
102
|
- [`set_style_name`](#set_style_name)
|
|
103
|
+
- [`set_version`](#set_version)
|
|
102
104
|
- [`set_vertical_metrics`](#set_vertical_metrics)
|
|
103
105
|
- [`subset`](#subset)
|
|
104
106
|
- [`to_sliced_variable`](#to_sliced_variable)
|
|
@@ -720,13 +722,48 @@ instance = font.get_variable_instance_closest_to_coordinates(
|
|
|
720
722
|
#### `get_version`
|
|
721
723
|
```python
|
|
722
724
|
"""
|
|
723
|
-
Gets the font version.
|
|
725
|
+
Gets the font version reading it from head.fontRevision,
|
|
726
|
+
with fallback on the version name record (name id 5) parsed value,
|
|
727
|
+
eg. "Version 1.015;git-0a5106e0b" -> 1.015.
|
|
724
728
|
|
|
725
|
-
:
|
|
729
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
730
|
+
:type use_head_revision: bool
|
|
731
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
732
|
+
:type use_name_record: bool
|
|
733
|
+
|
|
734
|
+
:returns: The font version value, 0.0 if the version cannot be read.
|
|
726
735
|
:rtype: float
|
|
736
|
+
|
|
737
|
+
:raises ArgumentError: If both options are False.
|
|
727
738
|
"""
|
|
728
739
|
|
|
729
|
-
version = font.get_version()
|
|
740
|
+
version = font.get_version(use_head_revision=True, use_name_record=True)
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
#### `get_version_formatted`
|
|
744
|
+
```python
|
|
745
|
+
"""
|
|
746
|
+
Gets the font version formatted using the version name record convention,
|
|
747
|
+
with the given prefix and a minimum of 3 decimal digits, eg. "v1.015".
|
|
748
|
+
|
|
749
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
750
|
+
:type use_head_revision: bool
|
|
751
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
752
|
+
:type use_name_record: bool
|
|
753
|
+
:param prefix: The prefix to prepend to the version value.
|
|
754
|
+
:type prefix: str
|
|
755
|
+
|
|
756
|
+
:returns: The formatted font version value, eg. "v0.000" if the version cannot be read.
|
|
757
|
+
:rtype: str
|
|
758
|
+
|
|
759
|
+
:raises ArgumentError: If both source options are False.
|
|
760
|
+
"""
|
|
761
|
+
|
|
762
|
+
version = font.get_version_formatted(
|
|
763
|
+
use_head_revision=True,
|
|
764
|
+
use_name_record=True,
|
|
765
|
+
prefix="v",
|
|
766
|
+
)
|
|
730
767
|
```
|
|
731
768
|
|
|
732
769
|
#### `get_vertical_metrics`
|
|
@@ -1176,6 +1213,28 @@ Sets the style name updating the related font names records.
|
|
|
1176
1213
|
font.set_style_name(name="Bold Italic")
|
|
1177
1214
|
```
|
|
1178
1215
|
|
|
1216
|
+
#### `set_version`
|
|
1217
|
+
```python
|
|
1218
|
+
"""
|
|
1219
|
+
Sets the font version, the version value can be a number (eg. 1.015)
|
|
1220
|
+
or a version string (eg. "Version 1.015"), parsed the same way the
|
|
1221
|
+
version name record value is parsed when read.
|
|
1222
|
+
The head.fontRevision and the version name record (name id 5) are
|
|
1223
|
+
updated, the latter is overwritten with the canonical "Version X.YYY"
|
|
1224
|
+
form (any extra info it contained is dropped).
|
|
1225
|
+
The unique identifier name record (name id 3) is updated only if its
|
|
1226
|
+
first ";" separated part holds the current version value, and only in
|
|
1227
|
+
that part. The CFF version is updated only if the font already has it.
|
|
1228
|
+
|
|
1229
|
+
:param version: The version value, eg. 1.015 or "Version 1.015"
|
|
1230
|
+
:type version: float or str
|
|
1231
|
+
|
|
1232
|
+
:raises ArgumentError: If the version value is not valid.
|
|
1233
|
+
"""
|
|
1234
|
+
|
|
1235
|
+
font.set_version(1.015)
|
|
1236
|
+
```
|
|
1237
|
+
|
|
1179
1238
|
#### `set_vertical_metrics`
|
|
1180
1239
|
```python
|
|
1181
1240
|
"""
|
|
@@ -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)
|
|
@@ -93,14 +93,3 @@ def get_filename(
|
|
|
93
93
|
extension = get_format(ttfont)
|
|
94
94
|
filename = f"{basename}.{extension}"
|
|
95
95
|
return filename
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def get_version(
|
|
99
|
-
ttfont: TTFont,
|
|
100
|
-
) -> float:
|
|
101
|
-
"""
|
|
102
|
-
Gets the version of the given font (head.fontRevision).
|
|
103
|
-
"""
|
|
104
|
-
head = ttfont.get("head")
|
|
105
|
-
version = float(head.fontRevision)
|
|
106
|
-
return version
|
|
@@ -29,6 +29,7 @@ from fontbro import support as _support
|
|
|
29
29
|
from fontbro import tables as _tables
|
|
30
30
|
from fontbro import unicode as _unicode
|
|
31
31
|
from fontbro import variable as _variable
|
|
32
|
+
from fontbro import version as _version
|
|
32
33
|
from fontbro.exceptions import (
|
|
33
34
|
ArgumentError,
|
|
34
35
|
OperationError,
|
|
@@ -1027,15 +1028,62 @@ class Font:
|
|
|
1027
1028
|
|
|
1028
1029
|
def get_version(
|
|
1029
1030
|
self,
|
|
1031
|
+
*,
|
|
1032
|
+
use_head_revision: bool = True,
|
|
1033
|
+
use_name_record: bool = True,
|
|
1030
1034
|
) -> float:
|
|
1031
1035
|
"""
|
|
1032
|
-
Gets the font version.
|
|
1036
|
+
Gets the font version reading it from head.fontRevision,
|
|
1037
|
+
with fallback on the version name record (name id 5) parsed value,
|
|
1038
|
+
eg. "Version 1.015;git-0a5106e0b" -> 1.015.
|
|
1039
|
+
|
|
1040
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
1041
|
+
:type use_head_revision: bool
|
|
1042
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
1043
|
+
:type use_name_record: bool
|
|
1033
1044
|
|
|
1034
|
-
:returns: The font version value.
|
|
1045
|
+
:returns: The font version value, 0.0 if the version cannot be read.
|
|
1035
1046
|
:rtype: float
|
|
1047
|
+
|
|
1048
|
+
:raises ArgumentError: If both options are False.
|
|
1049
|
+
"""
|
|
1050
|
+
ttfont = self.get_ttfont()
|
|
1051
|
+
return _version.get_version(
|
|
1052
|
+
ttfont,
|
|
1053
|
+
use_head_revision=use_head_revision,
|
|
1054
|
+
use_name_record=use_name_record,
|
|
1055
|
+
)
|
|
1056
|
+
|
|
1057
|
+
def get_version_formatted(
|
|
1058
|
+
self,
|
|
1059
|
+
*,
|
|
1060
|
+
use_head_revision: bool = True,
|
|
1061
|
+
use_name_record: bool = True,
|
|
1062
|
+
prefix: str = "v",
|
|
1063
|
+
) -> str:
|
|
1064
|
+
"""
|
|
1065
|
+
Gets the font version formatted using the version name record convention,
|
|
1066
|
+
with the given prefix and a minimum of 3 decimal digits, eg. "v1.015".
|
|
1067
|
+
|
|
1068
|
+
:param use_head_revision: If True, the head.fontRevision value is used (if set).
|
|
1069
|
+
:type use_head_revision: bool
|
|
1070
|
+
:param use_name_record: If True, the version name record value is used as fallback.
|
|
1071
|
+
:type use_name_record: bool
|
|
1072
|
+
:param prefix: The prefix to prepend to the version value.
|
|
1073
|
+
:type prefix: str
|
|
1074
|
+
|
|
1075
|
+
:returns: The formatted font version value, eg. "v0.000" if the version cannot be read.
|
|
1076
|
+
:rtype: str
|
|
1077
|
+
|
|
1078
|
+
:raises ArgumentError: If both source options are False.
|
|
1036
1079
|
"""
|
|
1037
1080
|
ttfont = self.get_ttfont()
|
|
1038
|
-
return
|
|
1081
|
+
return _version.get_version_formatted(
|
|
1082
|
+
ttfont,
|
|
1083
|
+
use_head_revision=use_head_revision,
|
|
1084
|
+
use_name_record=use_name_record,
|
|
1085
|
+
prefix=prefix,
|
|
1086
|
+
)
|
|
1039
1087
|
|
|
1040
1088
|
def get_vertical_metrics(
|
|
1041
1089
|
self,
|
|
@@ -1670,6 +1718,29 @@ class Font:
|
|
|
1670
1718
|
style_name=name,
|
|
1671
1719
|
)
|
|
1672
1720
|
|
|
1721
|
+
def set_version(
|
|
1722
|
+
self,
|
|
1723
|
+
version: float | str,
|
|
1724
|
+
) -> None:
|
|
1725
|
+
"""
|
|
1726
|
+
Sets the font version, the version value can be a number (eg. 1.015)
|
|
1727
|
+
or a version string (eg. "Version 1.015"), parsed the same way the
|
|
1728
|
+
version name record value is parsed when read.
|
|
1729
|
+
The head.fontRevision and the version name record (name id 5) are
|
|
1730
|
+
updated, the latter is overwritten with the canonical "Version X.YYY"
|
|
1731
|
+
form (any extra info it contained is dropped).
|
|
1732
|
+
The unique identifier name record (name id 3) is updated only if its
|
|
1733
|
+
first ";" separated part holds the current version value, and only in
|
|
1734
|
+
that part. The CFF version is updated only if the font already has it.
|
|
1735
|
+
|
|
1736
|
+
:param version: The version value, eg. 1.015 or "Version 1.015"
|
|
1737
|
+
:type version: float or str
|
|
1738
|
+
|
|
1739
|
+
:raises ArgumentError: If the version value is not valid.
|
|
1740
|
+
"""
|
|
1741
|
+
ttfont = self.get_ttfont()
|
|
1742
|
+
_version.set_version(ttfont, version)
|
|
1743
|
+
|
|
1673
1744
|
def set_vertical_metrics(
|
|
1674
1745
|
self,
|
|
1675
1746
|
**vertical_metrics: Any,
|