TTFQuery 2.0.1a1__tar.gz → 2.1.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.
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/PKG-INFO +9 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/PKG-INFO +9 -3
- ttfquery-2.1.0/pyproject.toml +102 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/setup.py +4 -4
- ttfquery-2.1.0/tests/test_describe.py +56 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/tests/test_findsystem_linux.py +3 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/tests/test_findsystem_win32.py +4 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/tests/test_glyphquery.py +10 -8
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/tests/test_registry.py +6 -5
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/__init__.py +1 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/_scriptregistry.py +3 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/describe.py +33 -27
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/findsystem.py +24 -21
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/glyph.py +5 -5
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/glyphquery.py +8 -8
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/guessdescription.py +5 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/scriptregistry.py +3 -2
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/ttffamily.py +1 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/ttffiles.py +23 -24
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/ttfgroups.py +9 -6
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/ttfquery/ttfmetadata.py +3 -3
- ttfquery-2.0.1a1/pyproject.toml +0 -55
- ttfquery-2.0.1a1/tests/test_describe.py +0 -20
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/MANIFEST.in +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/README.md +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/SOURCES.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/dependency_links.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/entry_points.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/requires.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/TTFQuery.egg-info/top_level.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/license.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TTFQuery
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: FontTools-based package for querying system fonts
|
|
5
5
|
Home-page: http://ttfquery.sourceforge.net/
|
|
6
6
|
Author: Mike C. Fletcher
|
|
@@ -46,12 +46,18 @@ License: THIS SOFTWARE IS NOT FAULT TOLERANT AND SHOULD NOT BE USED IN ANY
|
|
|
46
46
|
Project-URL: Homepage, http://ttfquery.sourceforge.net/
|
|
47
47
|
Keywords: fonttools,ttf,truetype,outline,font,curve,system fonts
|
|
48
48
|
Platform: Any
|
|
49
|
-
Classifier: Programming Language :: Python
|
|
49
|
+
Classifier: Programming Language :: Python :: 3
|
|
50
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
51
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
52
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
53
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
54
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
55
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
50
56
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
51
57
|
Classifier: Intended Audience :: Developers
|
|
52
58
|
Classifier: Operating System :: OS Independent
|
|
53
59
|
Classifier: Topic :: Multimedia :: Graphics
|
|
54
|
-
Requires-Python: >=3.
|
|
60
|
+
Requires-Python: >=3.9
|
|
55
61
|
Description-Content-Type: text/markdown
|
|
56
62
|
Requires-Dist: fonttools
|
|
57
63
|
Requires-Dist: numpy
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TTFQuery
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: FontTools-based package for querying system fonts
|
|
5
5
|
Home-page: http://ttfquery.sourceforge.net/
|
|
6
6
|
Author: Mike C. Fletcher
|
|
@@ -46,12 +46,18 @@ License: THIS SOFTWARE IS NOT FAULT TOLERANT AND SHOULD NOT BE USED IN ANY
|
|
|
46
46
|
Project-URL: Homepage, http://ttfquery.sourceforge.net/
|
|
47
47
|
Keywords: fonttools,ttf,truetype,outline,font,curve,system fonts
|
|
48
48
|
Platform: Any
|
|
49
|
-
Classifier: Programming Language :: Python
|
|
49
|
+
Classifier: Programming Language :: Python :: 3
|
|
50
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
51
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
52
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
53
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
54
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
55
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
50
56
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
51
57
|
Classifier: Intended Audience :: Developers
|
|
52
58
|
Classifier: Operating System :: OS Independent
|
|
53
59
|
Classifier: Topic :: Multimedia :: Graphics
|
|
54
|
-
Requires-Python: >=3.
|
|
60
|
+
Requires-Python: >=3.9
|
|
55
61
|
Description-Content-Type: text/markdown
|
|
56
62
|
Requires-Dist: fonttools
|
|
57
63
|
Requires-Dist: numpy
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "TTFQuery"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "FontTools-based package for querying system fonts"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "license.txt" }
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Mike C. Fletcher", email = "mcfletch@users.sourceforge.net" },
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
dependencies = [
|
|
16
|
+
"fonttools",
|
|
17
|
+
"numpy",
|
|
18
|
+
]
|
|
19
|
+
keywords = [
|
|
20
|
+
"fonttools",
|
|
21
|
+
"ttf",
|
|
22
|
+
"truetype",
|
|
23
|
+
"outline",
|
|
24
|
+
"font",
|
|
25
|
+
"curve",
|
|
26
|
+
"system fonts",
|
|
27
|
+
]
|
|
28
|
+
classifiers = [
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
37
|
+
"Intended Audience :: Developers",
|
|
38
|
+
"Operating System :: OS Independent",
|
|
39
|
+
"Topic :: Multimedia :: Graphics",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "http://ttfquery.sourceforge.net/"
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
test = [
|
|
47
|
+
"pytest",
|
|
48
|
+
"pytest-cov",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
ttffiles = "ttfquery.ttffiles:main"
|
|
53
|
+
ttffamily = "ttfquery.ttffamily:main"
|
|
54
|
+
ttfgroups = "ttfquery.ttfgroups:main"
|
|
55
|
+
ttfmetadata = "ttfquery.ttfmetadata:main"
|
|
56
|
+
|
|
57
|
+
[tool.setuptools]
|
|
58
|
+
packages = ["ttfquery"]
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.dynamic]
|
|
61
|
+
version = { attr = "ttfquery.__version__" }
|
|
62
|
+
|
|
63
|
+
# uv decides whether its cached metadata for a source tree is still current
|
|
64
|
+
# from pyproject.toml, setup.py and setup.cfg alone. This project's version
|
|
65
|
+
# lives in ttfquery/__init__.py, so name that file too: without it a version
|
|
66
|
+
# bump leaves uv answering with the previous number, and a dependent requiring
|
|
67
|
+
# the new one resolves against PyPI rather than this checkout.
|
|
68
|
+
[tool.uv]
|
|
69
|
+
cache-keys = [{ file = "pyproject.toml" }, { file = "ttfquery/__init__.py" }]
|
|
70
|
+
|
|
71
|
+
# Named explicitly rather than left to ruff's default, which has widened
|
|
72
|
+
# between releases: a gate whose meaning moves when a tool is upgraded is not a
|
|
73
|
+
# gate. `E,W,F,B` is what the other pre-2010 projects here hold to.
|
|
74
|
+
[tool.ruff.lint]
|
|
75
|
+
select = ["E", "W", "F", "B"]
|
|
76
|
+
# `_name` as well as `_`: an underscore prefix is how Python says a name is
|
|
77
|
+
# bound but deliberately unused.
|
|
78
|
+
dummy-variable-rgx = "^(_[a-zA-Z0-9_]*|err)$"
|
|
79
|
+
ignore = [
|
|
80
|
+
'E501', # long lines, kept readable by hand
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
# The package's own declarations, checked as a consumer's checker reads them.
|
|
84
|
+
# `check_untyped_defs` rather than `disallow_untyped_defs`: this package is
|
|
85
|
+
# older than annotations, and its bodies being checked is the half that finds
|
|
86
|
+
# defects -- the other half is a job of its own, tracked as one.
|
|
87
|
+
[tool.mypy]
|
|
88
|
+
# Named here so that `mypy` with no arguments checks the package: the tox
|
|
89
|
+
# environment and a developer's bare `mypy` are then the same run.
|
|
90
|
+
files = ["ttfquery"]
|
|
91
|
+
python_version = "3.12"
|
|
92
|
+
check_untyped_defs = true
|
|
93
|
+
warn_unused_ignores = true
|
|
94
|
+
ignore_missing_imports = true
|
|
95
|
+
|
|
96
|
+
# `findsystem` reads the Windows font directories out of the registry, and
|
|
97
|
+
# `winreg` is a module Linux does not have. Checked as Windows sees it in a
|
|
98
|
+
# second run -- see tools/preflight.toml -- so this keeps the Linux run from
|
|
99
|
+
# reporting nine absent names as defects.
|
|
100
|
+
[[tool.mypy.overrides]]
|
|
101
|
+
module = "ttfquery.findsystem"
|
|
102
|
+
disable_error_code = ["attr-defined"]
|
|
@@ -5,7 +5,7 @@ Run:
|
|
|
5
5
|
python setup.py install
|
|
6
6
|
to install the package from the source archive.
|
|
7
7
|
"""
|
|
8
|
-
import
|
|
8
|
+
import os
|
|
9
9
|
from setuptools import setup
|
|
10
10
|
HERE = os.path.dirname(__file__)
|
|
11
11
|
|
|
@@ -32,9 +32,9 @@ if __name__ == "__main__":
|
|
|
32
32
|
'ttfquery':'ttfquery',
|
|
33
33
|
},
|
|
34
34
|
packages = [
|
|
35
|
-
'ttfquery',
|
|
35
|
+
'ttfquery',
|
|
36
36
|
],
|
|
37
|
-
|
|
37
|
+
install_requires = ['fonttools','numpy'],
|
|
38
38
|
classifiers= [
|
|
39
39
|
"""Programming Language :: Python""",
|
|
40
40
|
"""Topic :: Software Development :: Libraries :: Python Modules""",
|
|
@@ -74,4 +74,4 @@ which TTFQuery was refactored.
|
|
|
74
74
|
]
|
|
75
75
|
}
|
|
76
76
|
)
|
|
77
|
-
|
|
77
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
from ttfquery import describe, findsystem
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
class TestDescribe(unittest.TestCase):
|
|
6
|
+
def test_describe_system_fonts(self):
|
|
7
|
+
for fontfile in list(findsystem.findFonts())[:100]:
|
|
8
|
+
try:
|
|
9
|
+
font = describe.openFont(fontfile)
|
|
10
|
+
except Exception as err:
|
|
11
|
+
err.args += ('Error opening font', font)
|
|
12
|
+
raise
|
|
13
|
+
else:
|
|
14
|
+
short = describe.shortName( font )
|
|
15
|
+
assert short, "Null name for font %s"%(fontfile,)
|
|
16
|
+
family = describe.family( font )
|
|
17
|
+
assert len(family)==2, family
|
|
18
|
+
modifiers = describe.modifiers( font )
|
|
19
|
+
assert describe.weightName(modifiers[0])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestTheNameIsText:
|
|
23
|
+
"""`shortName` answers what the font calls itself, as text.
|
|
24
|
+
|
|
25
|
+
A name record is bytes in one of two encodings, and answering those bytes
|
|
26
|
+
put `b'Open Sans'` into every message that named a font and left the font
|
|
27
|
+
registry decoding what this had just encoded.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def a_font(self):
|
|
31
|
+
from ttfquery import findsystem
|
|
32
|
+
for path in findsystem.findFonts():
|
|
33
|
+
try:
|
|
34
|
+
return describe.openFont(path)
|
|
35
|
+
except Exception:
|
|
36
|
+
continue
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
def test_both_halves_are_strings(self):
|
|
40
|
+
font = self.a_font()
|
|
41
|
+
if font is None:
|
|
42
|
+
import pytest
|
|
43
|
+
pytest.skip('no readable font on this machine')
|
|
44
|
+
name, family = describe.shortName(font)
|
|
45
|
+
assert isinstance(name, str), repr(name)
|
|
46
|
+
assert isinstance(family, str), repr(family)
|
|
47
|
+
|
|
48
|
+
def test_a_two_byte_record_is_read_as_utf_16(self):
|
|
49
|
+
assert describe._recordText('Ångstrom'.encode('utf-16-be')) == \
|
|
50
|
+
'Ångstrom'
|
|
51
|
+
|
|
52
|
+
def test_a_single_byte_record_is_read_as_latin_1(self):
|
|
53
|
+
assert describe._recordText(b'Open Sans') == 'Open Sans'
|
|
54
|
+
|
|
55
|
+
def test_text_is_left_as_it_is(self):
|
|
56
|
+
assert describe._recordText('Open Sans') == 'Open Sans'
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
2
|
from ttfquery import findsystem
|
|
3
3
|
import pytest
|
|
4
|
-
import sys
|
|
4
|
+
import sys
|
|
5
|
+
import unittest
|
|
5
6
|
pytestmark = pytest.mark.skipif(
|
|
6
|
-
not sys.platform.startswith('linux'),
|
|
7
|
+
not sys.platform.startswith('linux'),
|
|
7
8
|
reason='Linux tests'
|
|
8
9
|
)
|
|
9
10
|
|
|
@@ -15,4 +16,3 @@ class TestLinux(unittest.TestCase):
|
|
|
15
16
|
def test_fonts_from_registry(self):
|
|
16
17
|
fonts = findsystem.findFonts()
|
|
17
18
|
assert fonts, "No fonts were found in our default font-search paths"
|
|
18
|
-
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
2
|
from ttfquery import findsystem
|
|
3
3
|
import pytest
|
|
4
|
-
import
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import glob
|
|
7
|
+
import unittest
|
|
5
8
|
pytestmark = pytest.mark.skipif(not sys.platform == 'win32', reason='Win32 tests')
|
|
6
9
|
|
|
7
10
|
class TestWin32(unittest.TestCase):
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
2
|
from ttfquery import ttffiles, describe, glyphquery, glyph
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import os
|
|
4
|
+
import unittest
|
|
5
|
+
import tempfile
|
|
6
|
+
import shutil
|
|
5
7
|
|
|
6
8
|
class TestGlyphQuery(unittest.TestCase):
|
|
7
9
|
def setUp(self):
|
|
@@ -17,15 +19,15 @@ class TestGlyphQuery(unittest.TestCase):
|
|
|
17
19
|
|
|
18
20
|
def test_has_a_glyph(self):
|
|
19
21
|
has,total = 0,0
|
|
20
|
-
for
|
|
22
|
+
for _name,metadata in self.registry.specificFonts.items():
|
|
21
23
|
font = describe.openFont(metadata.file_name)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
glyphquery.charHeight(font)
|
|
25
|
+
glyphquery.lineHeight(font)
|
|
26
|
+
glyphquery.charDescent(font)
|
|
25
27
|
if glyphquery.hasGlyph(font,'a'):
|
|
26
28
|
glyphName = glyphquery.explicitGlyph(font,'a')
|
|
27
29
|
if glyphName:
|
|
28
|
-
|
|
30
|
+
glyphquery.width(font,glyphName)
|
|
29
31
|
has += 1
|
|
30
32
|
|
|
31
33
|
shape = glyph.Glyph(glyphName)
|
|
@@ -38,7 +40,7 @@ class TestGlyphQuery(unittest.TestCase):
|
|
|
38
40
|
else:
|
|
39
41
|
glyphName = glyphquery.glyphName(font,'a')
|
|
40
42
|
assert glyphName, """Didn't get a placeholder for the 'a' character"""
|
|
41
|
-
|
|
43
|
+
glyphquery.width(font,glyphName)
|
|
42
44
|
total += 1
|
|
43
45
|
assert total, "No specific fonts on this system?"
|
|
44
46
|
assert has/float(total) > .2, "More than 4/5 of fonts on this system are missing a glyph for `a`? %s/%s"%(has,total)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import print_function
|
|
2
2
|
from ttfquery import ttffiles, ttfgroups, ttfmetadata, ttffamily
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import os
|
|
4
|
+
import unittest
|
|
5
|
+
import tempfile
|
|
6
|
+
import shutil
|
|
5
7
|
|
|
6
8
|
class TestRegistry(unittest.TestCase):
|
|
7
9
|
def setUp(self):
|
|
@@ -30,10 +32,10 @@ class TestRegistry(unittest.TestCase):
|
|
|
30
32
|
except KeyError:
|
|
31
33
|
pass
|
|
32
34
|
if font:
|
|
33
|
-
break
|
|
35
|
+
break
|
|
34
36
|
if not font:
|
|
35
37
|
raise RuntimeError("Unable to find any of Arial/Helvetica/SANS")
|
|
36
|
-
|
|
38
|
+
|
|
37
39
|
def test_ttfgroups(self):
|
|
38
40
|
registry = self.registry
|
|
39
41
|
table = ttfgroups.buildTable(registry)
|
|
@@ -56,4 +58,3 @@ class TestRegistry(unittest.TestCase):
|
|
|
56
58
|
ttffamily.search(registry,family)
|
|
57
59
|
for subfam in subfams.keys():
|
|
58
60
|
ttffamily.search(registry,family,subfam)
|
|
59
|
-
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Fonttools package for querying and sorting system fonts"""
|
|
2
|
-
__version__ = "2.0
|
|
2
|
+
__version__ = "2.1.0"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""The singleton "registry" object (an instance of :class:`ttfquery.ttffiles.Registry`
|
|
2
|
-
is the only member of note). This registry with be created in a file
|
|
3
|
-
in the user's $HOME directory ``.font.cache`` if the $HOME environment variable
|
|
4
|
-
is defined. Otherwise will be created in the ttfquery source code directory
|
|
2
|
+
is the only member of note). This registry with be created in a file
|
|
3
|
+
in the user's $HOME directory ``.font.cache`` if the $HOME environment variable
|
|
4
|
+
is defined. Otherwise will be created in the ttfquery source code directory
|
|
5
5
|
(which is obviously not a very good solution).
|
|
6
6
|
|
|
7
7
|
.. note::
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
"""Extract meta-data from a font-file to describe the font"""
|
|
2
|
-
|
|
2
|
+
import logging
|
|
3
3
|
import sys
|
|
4
|
+
from typing import Dict, List
|
|
5
|
+
|
|
6
|
+
from fontTools import ttLib
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
unicode = str
|
|
9
|
-
long = int
|
|
10
|
-
try:
|
|
11
|
-
from OpenGLContext.debug.logs import text_log
|
|
12
|
-
except ImportError:
|
|
13
|
-
text_log = None
|
|
8
|
+
unicode = str
|
|
9
|
+
long = int
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
14
11
|
|
|
15
12
|
|
|
16
13
|
def openFont(filename):
|
|
@@ -24,21 +21,33 @@ FONT_SPECIFIER_NAME_ID = 4
|
|
|
24
21
|
FONT_SPECIFIER_FAMILY_ID = 1
|
|
25
22
|
|
|
26
23
|
|
|
24
|
+
def _recordText(value):
|
|
25
|
+
"""A name record as text, whichever way the font stored it.
|
|
26
|
+
|
|
27
|
+
A record is bytes in one of two encodings and the font does not say which:
|
|
28
|
+
UTF-16BE where it carries the NUL bytes of one, and a single-byte encoding
|
|
29
|
+
otherwise -- Latin-1, which is what the Macintosh Roman a name table names
|
|
30
|
+
agrees with for the characters a font name uses.
|
|
31
|
+
"""
|
|
32
|
+
if not isinstance(value, bytes):
|
|
33
|
+
return value
|
|
34
|
+
return (value.decode("utf-16-be") if b"\000" in value
|
|
35
|
+
else value.decode("latin-1"))
|
|
36
|
+
|
|
37
|
+
|
|
27
38
|
def shortName(font):
|
|
28
|
-
"""
|
|
39
|
+
"""The font's own name and its family's, as text
|
|
40
|
+
|
|
41
|
+
``('Open Sans Bold Italic', 'Open Sans')`` -- what the font calls itself,
|
|
42
|
+
and the family it belongs to.
|
|
43
|
+
"""
|
|
29
44
|
name = ""
|
|
30
45
|
family = ""
|
|
31
46
|
for record in font["name"].names:
|
|
32
47
|
if record.nameID == FONT_SPECIFIER_NAME_ID and not name:
|
|
33
|
-
|
|
34
|
-
name = unicode(record.string, "utf-16-be").encode("utf-8")
|
|
35
|
-
else:
|
|
36
|
-
name = record.string
|
|
48
|
+
name = _recordText(record.string)
|
|
37
49
|
elif record.nameID == FONT_SPECIFIER_FAMILY_ID and not family:
|
|
38
|
-
|
|
39
|
-
family = unicode(record.string, "utf-16-be").encode("utf-8")
|
|
40
|
-
else:
|
|
41
|
-
family = record.string
|
|
50
|
+
family = _recordText(record.string)
|
|
42
51
|
if name and family:
|
|
43
52
|
break
|
|
44
53
|
return name, family
|
|
@@ -183,7 +192,9 @@ WEIGHT_NAMES = {
|
|
|
183
192
|
"black": 900,
|
|
184
193
|
"heavy": 900,
|
|
185
194
|
}
|
|
186
|
-
|
|
195
|
+
#: Every name for each weight, so a number reads back as the words a font
|
|
196
|
+
#: might have used for it.
|
|
197
|
+
WEIGHT_NUMBERS: Dict[int, List[str]] = {}
|
|
187
198
|
for key, value in WEIGHT_NAMES.items():
|
|
188
199
|
WEIGHT_NUMBERS.setdefault(value, []).append(key)
|
|
189
200
|
|
|
@@ -231,8 +242,7 @@ def familyNames(familyID, subFamilyID=0):
|
|
|
231
242
|
"""Convert family integers to human-readable names"""
|
|
232
243
|
familyName, subFamilies = FAMILY_NAMES.get(familyID, ("RESERVED", None))
|
|
233
244
|
if familyName == "RESERVED":
|
|
234
|
-
|
|
235
|
-
text_log.warn("Font has invalid (reserved) familyID: %s", familyID)
|
|
245
|
+
log.warning("Font has invalid (reserved) familyID: %s", familyID)
|
|
236
246
|
if subFamilies:
|
|
237
247
|
subFamily = subFamilies.get(subFamilyID, "RESERVED")
|
|
238
248
|
else:
|
|
@@ -279,11 +289,7 @@ def guessEncoding(font, given=None):
|
|
|
279
289
|
"""
|
|
280
290
|
if isinstance(given, tuple) and given:
|
|
281
291
|
if len(given) == 2:
|
|
282
|
-
|
|
283
|
-
if text_log:
|
|
284
|
-
text_log.info(
|
|
285
|
-
"""Checking for explicitly required encoding %r""", given
|
|
286
|
-
)
|
|
292
|
+
log.debug("Checking for explicitly required encoding %r", given)
|
|
287
293
|
if not font["cmap"].getcmap(*given):
|
|
288
294
|
raise ValueError(
|
|
289
295
|
"""The specified font encoding %r does not appear to be available within the font %r. Available encodings: %s"""
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
"""Find system fonts (only works on Linux and Win32 at the moment)"""
|
|
2
2
|
from __future__ import print_function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
import glob
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
unicode = str
|
|
8
9
|
|
|
9
10
|
def win32FontDirectory( ):
|
|
10
11
|
"""Get User-specific font directory on Win32"""
|
|
11
12
|
try:
|
|
12
|
-
import
|
|
13
|
+
import winreg
|
|
13
14
|
except ImportError:
|
|
14
15
|
return os.path.join(os.environ['WINDIR'], 'Fonts')
|
|
15
16
|
else:
|
|
16
|
-
k =
|
|
17
|
-
|
|
17
|
+
k = winreg.OpenKey(
|
|
18
|
+
winreg.HKEY_CURRENT_USER,
|
|
18
19
|
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
|
|
19
20
|
)
|
|
20
21
|
try:
|
|
21
22
|
# should check that k is valid? How?
|
|
22
|
-
return
|
|
23
|
+
return winreg.QueryValueEx( k, "Fonts" )[0]
|
|
23
24
|
finally:
|
|
24
|
-
|
|
25
|
+
winreg.CloseKey( k )
|
|
25
26
|
|
|
26
27
|
def win32InstalledFonts( fontDirectory = None ):
|
|
27
28
|
"""Get list of explicitly *installed* font names
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
IFF there is no registry entry for installed fonts,
|
|
30
31
|
likely due to a too-new windows install, then we'll
|
|
31
32
|
just return all .ttf files in fontDirectory
|
|
32
33
|
"""
|
|
33
|
-
import
|
|
34
|
+
import winreg
|
|
34
35
|
if fontDirectory is None:
|
|
35
36
|
fontDirectory = win32FontDirectory()
|
|
36
37
|
k = None
|
|
@@ -40,32 +41,34 @@ def win32InstalledFonts( fontDirectory = None ):
|
|
|
40
41
|
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Fonts",
|
|
41
42
|
):
|
|
42
43
|
try:
|
|
43
|
-
k =
|
|
44
|
-
|
|
44
|
+
k = winreg.OpenKey(
|
|
45
|
+
winreg.HKEY_LOCAL_MACHINE,
|
|
45
46
|
keyName
|
|
46
47
|
)
|
|
47
48
|
except OSError as err:
|
|
48
49
|
pass
|
|
50
|
+
else:
|
|
51
|
+
break
|
|
49
52
|
if not k:
|
|
50
53
|
# couldn't open either WinNT or Win98 key???
|
|
51
54
|
return glob.glob( os.path.join(fontDirectory, '*.ttf'))
|
|
52
55
|
try:
|
|
53
56
|
# should check that k is valid? How?
|
|
54
|
-
for index in range(
|
|
55
|
-
key,value,_ =
|
|
57
|
+
for index in range( winreg.QueryInfoKey(k)[1]):
|
|
58
|
+
key,value,_ = winreg.EnumValue( k, index )
|
|
56
59
|
if not os.path.dirname( value ):
|
|
57
60
|
value = os.path.join( fontDirectory, value )
|
|
58
61
|
value = os.path.abspath( value ).lower()
|
|
59
62
|
if value[-4:] == '.ttf':
|
|
60
63
|
items[ value ] = 1
|
|
61
|
-
return items.keys()
|
|
64
|
+
return list(items.keys())
|
|
62
65
|
finally:
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
winreg.CloseKey( k )
|
|
67
|
+
|
|
65
68
|
|
|
66
69
|
def linuxFontDirectories( ):
|
|
67
70
|
"""Get system font directories on Linux/Unix
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
Uses /usr/sbin/chkfontpath to get the list
|
|
70
73
|
of system-font directories, note that many
|
|
71
74
|
of these will *not* be truetype font directories.
|
|
@@ -101,7 +104,7 @@ def linuxFontDirectories( ):
|
|
|
101
104
|
"/System/Library/Fonts/",
|
|
102
105
|
"System Folder:Fonts:",
|
|
103
106
|
]
|
|
104
|
-
|
|
107
|
+
|
|
105
108
|
set = []
|
|
106
109
|
for directory in directories:
|
|
107
110
|
directory = directory = os.path.expanduser( os.path.expandvars(directory))
|
|
@@ -21,7 +21,7 @@ class Glyph( object):
|
|
|
21
21
|
]
|
|
22
22
|
self.width = glyphquery.width( font, self.glyphName )
|
|
23
23
|
self.height = glyphquery.lineHeight( font )
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def calculateContours( self, font ):
|
|
26
26
|
"""Given a character, determine contours to draw
|
|
27
27
|
|
|
@@ -85,7 +85,7 @@ class Glyph( object):
|
|
|
85
85
|
list(flags[last:])+list(flags[last:])
|
|
86
86
|
) ))
|
|
87
87
|
return contours
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
def decomposeOutline( contour, steps=3 ):
|
|
90
90
|
"""Decompose a single TrueType contour to a line-loop
|
|
91
91
|
|
|
@@ -118,14 +118,14 @@ def decomposeOutline( contour, steps=3 ):
|
|
|
118
118
|
set = contour[:]
|
|
119
119
|
def on( record ):
|
|
120
120
|
"""Is this record on the contour?
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
record = ((Ax,Ay),Af)
|
|
123
123
|
"""
|
|
124
124
|
return record[-1] == 1
|
|
125
125
|
|
|
126
126
|
def merge( first, second):
|
|
127
127
|
"""Merge two off-point records into an on-point record"""
|
|
128
|
-
((Ax,Ay),Af) = first
|
|
128
|
+
((Ax,Ay),Af) = first
|
|
129
129
|
((Bx,By),Bf) = second
|
|
130
130
|
return (((Ax+Bx)/2.0),((Ay+By))/2.0),1
|
|
131
131
|
# create an expanded set so that all adjacent
|
|
@@ -152,7 +152,7 @@ def decomposeOutline( contour, steps=3 ):
|
|
|
152
152
|
if len(expanded) == 2: #KH
|
|
153
153
|
assert on(expanded[0]), """Expanded outline finishes off-curve""" #KH
|
|
154
154
|
result.append( expanded[1][0] ) #KH
|
|
155
|
-
del expanded[:1]
|
|
155
|
+
del expanded[:1]
|
|
156
156
|
break
|
|
157
157
|
assert on(expanded[2]), "Expanded outline doesn't have proper format!"
|
|
158
158
|
points = integrateQuadratic( expanded[:3], steps = steps )
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Glyph-specific queries on font-files"""
|
|
2
|
+
import logging
|
|
3
|
+
|
|
2
4
|
from ttfquery import describe
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
except ImportError:
|
|
6
|
-
text_log = None
|
|
5
|
+
|
|
6
|
+
log = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
8
|
def hasGlyph( font, char, encoding=None ):
|
|
9
9
|
"""Check to see if font appears to have explicit glyph for char"""
|
|
@@ -35,8 +35,8 @@ def glyphName( font, char, encoding=None, warnOnFailure=1 ):
|
|
|
35
35
|
glyfName = table.cmap.get( -1)
|
|
36
36
|
if glyfName is None:
|
|
37
37
|
glyfName = font['glyf'].glyphOrder[0]
|
|
38
|
-
if
|
|
39
|
-
|
|
38
|
+
if warnOnFailure:
|
|
39
|
+
log.warning(
|
|
40
40
|
"""Unable to find glyph name for %r, in %r using first glyph in table (%r)""",
|
|
41
41
|
char,
|
|
42
42
|
describe.shortName(font),
|
|
@@ -54,10 +54,10 @@ def width( font, glyphName ):
|
|
|
54
54
|
"""
|
|
55
55
|
try:
|
|
56
56
|
return font['hmtx'].metrics[ glyphName ][0]
|
|
57
|
-
except KeyError:
|
|
57
|
+
except KeyError as err:
|
|
58
58
|
raise ValueError( """Couldn't find glyph for glyphName %r"""%(
|
|
59
59
|
glyphName,
|
|
60
|
-
))
|
|
60
|
+
)) from err
|
|
61
61
|
|
|
62
62
|
def lineHeight( font ):
|
|
63
63
|
"""Get the base-line to base-line height for the font
|
|
@@ -16,6 +16,7 @@ XXX This is English-specific and entirely dependent on the
|
|
|
16
16
|
there will be a considerable number of cases where the
|
|
17
17
|
resulting name and flags will be incorrect.
|
|
18
18
|
"""
|
|
19
|
+
from typing import Any, Dict
|
|
19
20
|
WEIGHTS = [
|
|
20
21
|
'demibold', 'extrabold', 'semibold', 'ultrabold', 'bold',
|
|
21
22
|
'ultralight', 'extralight', 'light',
|
|
@@ -48,12 +49,13 @@ WEIGHT_SYNONYMS = [
|
|
|
48
49
|
WEIGHT_MODIFIERS = [
|
|
49
50
|
'extra', 'ultra'
|
|
50
51
|
]
|
|
51
|
-
|
|
52
|
+
|
|
52
53
|
|
|
53
54
|
ITALIC_INDICATORS = [
|
|
54
55
|
'italic', 'ital','itali', 'it', 'bolditalic',
|
|
55
56
|
]
|
|
56
|
-
|
|
57
|
+
#: The fonts a scan of the system found, by the name it was asked for.
|
|
58
|
+
SYSTEM_FONTS: Dict[str, Any] = {}
|
|
57
59
|
|
|
58
60
|
def interpretModifiers( name ):
|
|
59
61
|
"""Heuristic attempt to get weight and italic data from font-name
|
|
@@ -130,6 +132,6 @@ def get( name, style=None ):
|
|
|
130
132
|
if key[0] == style[0]:
|
|
131
133
|
return value
|
|
132
134
|
# well, there's at least one font here, use it...
|
|
133
|
-
for
|
|
135
|
+
for _key, value in set.items():
|
|
134
136
|
return value
|
|
135
137
|
return None
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
"""Provides a single font metadata cache from which multiple programs can run
|
|
2
2
|
|
|
3
|
-
Note: on systems without an XDG_CACHE_HOME or a HOME environment variable
|
|
3
|
+
Note: on systems without an XDG_CACHE_HOME or a HOME environment variable
|
|
4
4
|
this will store the cache in the *code* directory for ttfquery, which is
|
|
5
5
|
obviously sub-optimal.
|
|
6
6
|
|
|
7
7
|
`registryFile` -- calculated at load time as the location for the cache
|
|
8
8
|
"""
|
|
9
9
|
from ttfquery import ttffiles
|
|
10
|
-
import os
|
|
10
|
+
import os
|
|
11
|
+
import logging
|
|
11
12
|
log = logging.getLogger( __name__ )
|
|
12
13
|
|
|
13
14
|
### more robust registry-file location by John Hunter...
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
"""Registry of available TrueType font files"""
|
|
2
2
|
from ttfquery import describe, findsystem
|
|
3
|
-
import traceback
|
|
3
|
+
import traceback
|
|
4
|
+
import os
|
|
4
5
|
try:
|
|
5
|
-
import cPickle as pickle
|
|
6
|
+
import cPickle as pickle
|
|
6
7
|
except ImportError:
|
|
7
8
|
import pickle
|
|
8
|
-
|
|
9
|
-
unicode
|
|
10
|
-
except NameError:
|
|
11
|
-
unicode = str
|
|
12
|
-
import logging
|
|
13
|
-
log =logging.getLogger( __name__ )
|
|
9
|
+
import logging
|
|
14
10
|
from collections import namedtuple
|
|
15
11
|
|
|
12
|
+
unicode = str
|
|
13
|
+
log = logging.getLogger( __name__ )
|
|
14
|
+
|
|
16
15
|
class FontMetadata(namedtuple(
|
|
17
16
|
'FontMetadata',
|
|
18
17
|
(
|
|
@@ -26,10 +25,10 @@ class FontMetadata(namedtuple(
|
|
|
26
25
|
"""Stores specific font metadata
|
|
27
26
|
|
|
28
27
|
A specific font is basically an actual font-file,
|
|
29
|
-
that is, it is one of a family of fonts which make
|
|
28
|
+
that is, it is one of a family of fonts which make
|
|
30
29
|
up the various "modified" versions of a font face.
|
|
31
30
|
|
|
32
|
-
So `Ubuntu Light Italic` would be a specific font
|
|
31
|
+
So `Ubuntu Light Italic` would be a specific font
|
|
33
32
|
that is a part of the font-face `Ubuntu` with the modifers
|
|
34
33
|
for `Light` and `Italic` applied.
|
|
35
34
|
|
|
@@ -67,7 +66,7 @@ class Registry(object):
|
|
|
67
66
|
specific font names
|
|
68
67
|
shortFiles -- mapping from font filename basenames
|
|
69
68
|
to font-file-lists
|
|
70
|
-
|
|
69
|
+
|
|
71
70
|
DIRTY -- flag indicating whether the registry has
|
|
72
71
|
had a new font registered (i.e. whether it should
|
|
73
72
|
be saved out to disk).
|
|
@@ -136,7 +135,7 @@ class Registry(object):
|
|
|
136
135
|
)
|
|
137
136
|
return FontMetadata(*[
|
|
138
137
|
(x.decode('utf-8') if isinstance(x,bytes) else x)
|
|
139
|
-
for x in result
|
|
138
|
+
for x in result
|
|
140
139
|
])
|
|
141
140
|
def register(
|
|
142
141
|
self,
|
|
@@ -160,7 +159,7 @@ class Registry(object):
|
|
|
160
159
|
if filename in self.files and not force:
|
|
161
160
|
return self.specificFonts.get( self.files[filename] )
|
|
162
161
|
self.dirty(1)
|
|
163
|
-
if modifiers
|
|
162
|
+
if modifiers is None:
|
|
164
163
|
(filename, modifiers, specificName, fontName, familySpecifier) = self.metadata(filename, force = force)
|
|
165
164
|
description = FontMetadata(filename, modifiers, specificName, fontName, familySpecifier)
|
|
166
165
|
try:
|
|
@@ -181,13 +180,13 @@ class Registry(object):
|
|
|
181
180
|
|
|
182
181
|
:param major: string description of major family
|
|
183
182
|
:param minor: optional string description of minor family
|
|
184
|
-
|
|
183
|
+
|
|
185
184
|
:rtype: list of font faces in the family
|
|
186
185
|
"""
|
|
187
186
|
major = major.upper()
|
|
188
187
|
if not minor:
|
|
189
188
|
result = []
|
|
190
|
-
for
|
|
189
|
+
for _key,set in self.families.get(major,{}).items():
|
|
191
190
|
result.extend( set.keys())
|
|
192
191
|
return result
|
|
193
192
|
minor = minor.upper()
|
|
@@ -215,7 +214,7 @@ class Registry(object):
|
|
|
215
214
|
return result
|
|
216
215
|
def fontForms( self, fontName ):
|
|
217
216
|
"""Retrieve the set of font-forms (weight,italics) available in a font
|
|
218
|
-
|
|
217
|
+
|
|
219
218
|
:param fontName: general font name to search
|
|
220
219
|
:rtype: list of two-tuples of (weight,italics) available in the font
|
|
221
220
|
"""
|
|
@@ -223,7 +222,7 @@ class Registry(object):
|
|
|
223
222
|
|
|
224
223
|
def fontFile( self, specificName ):
|
|
225
224
|
"""Return the absolute path-name for a given specific font
|
|
226
|
-
|
|
225
|
+
|
|
227
226
|
:param specificName: specific font name to search
|
|
228
227
|
:rtype: str(file_name) of the FontMetadata instance
|
|
229
228
|
"""
|
|
@@ -235,7 +234,7 @@ class Registry(object):
|
|
|
235
234
|
|
|
236
235
|
def matchName( self, name, single=0 ):
|
|
237
236
|
"""Try to find a general font based on a name
|
|
238
|
-
|
|
237
|
+
|
|
239
238
|
:param name: name to use to try to find the font, can match on any of
|
|
240
239
|
specific name, major family, or minor family
|
|
241
240
|
:param single: return the first match only (not a dictionary of results)
|
|
@@ -381,10 +380,10 @@ def get_options():
|
|
|
381
380
|
|
|
382
381
|
|
|
383
382
|
def main():
|
|
384
|
-
import logging
|
|
383
|
+
import logging
|
|
385
384
|
logging.basicConfig(level=logging.INFO)
|
|
386
385
|
options = get_options().parse_args()
|
|
387
|
-
|
|
386
|
+
registry_for_options(options)
|
|
388
387
|
return 0
|
|
389
388
|
|
|
390
389
|
def registry_for_options(options):
|
|
@@ -395,14 +394,14 @@ def registry_for_options(options):
|
|
|
395
394
|
else:
|
|
396
395
|
registry = Registry()
|
|
397
396
|
new = True
|
|
398
|
-
scan = new
|
|
397
|
+
scan = new
|
|
399
398
|
if getattr(options,'scan',False):
|
|
400
399
|
log.info("Forcing rescan of directories")
|
|
401
400
|
scan = True
|
|
402
401
|
if scan:
|
|
403
|
-
new,failed = registry.scan(
|
|
404
|
-
options.directories or None,
|
|
405
|
-
printErrors = False,
|
|
402
|
+
new,failed = registry.scan(
|
|
403
|
+
options.directories or None,
|
|
404
|
+
printErrors = False,
|
|
406
405
|
force = 1
|
|
407
406
|
)
|
|
408
407
|
if options.registry and registry.DIRTY:
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Demo script to print ordered set of system fonts"""
|
|
2
2
|
from __future__ import print_function
|
|
3
|
-
|
|
4
|
-
import
|
|
3
|
+
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
from ttfquery import ttffiles
|
|
6
|
+
import logging
|
|
5
7
|
log = logging.getLogger( __name__ )
|
|
6
8
|
|
|
7
9
|
def buildTable( registry ):
|
|
@@ -11,9 +13,10 @@ def buildTable( registry ):
|
|
|
11
13
|
otherwise the full set of system fonts provided
|
|
12
14
|
by findsystem will be used.
|
|
13
15
|
"""
|
|
14
|
-
|
|
16
|
+
#: family -> font name -> modifier set -> (font name, file name)
|
|
17
|
+
table: Dict[Any, Dict[Any, Dict[Any, Any]]] = {}
|
|
15
18
|
for major, minors in registry.families.items():
|
|
16
|
-
for
|
|
19
|
+
for _minor, fonts in minors.items():
|
|
17
20
|
for fontname in fonts.keys():
|
|
18
21
|
table.setdefault(major,{}).setdefault(fontname, {})
|
|
19
22
|
font = registry.fonts.get(fontname)
|
|
@@ -46,5 +49,5 @@ def run_report(table):
|
|
|
46
49
|
fnts = sorted( table[fam].items() )
|
|
47
50
|
for fnt,modset in fnts:
|
|
48
51
|
mods = sorted(modset.keys())
|
|
49
|
-
|
|
50
|
-
print(' ',fnt.ljust(32), '--',
|
|
52
|
+
shown = ",".join([ '%s%s'%( w, ['','(I)'][i&1]) for (w,i) in mods])
|
|
53
|
+
print(' ',fnt.ljust(32), '--', shown)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import print_function
|
|
4
4
|
#from ttfquery import describe
|
|
5
5
|
from ttfquery import ttffiles
|
|
6
|
-
import
|
|
6
|
+
import logging
|
|
7
7
|
|
|
8
8
|
def printMetaData( metadata ):
|
|
9
9
|
print(' Specific Name:', metadata.specific_name)
|
|
@@ -35,7 +35,7 @@ def find_match(name, registry):
|
|
|
35
35
|
specifics.sort()
|
|
36
36
|
for specific in specifics:
|
|
37
37
|
printMetaData( registry.metadata( registry.fontFile(specific) ))
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
|
|
40
40
|
if __name__ == "__main__":
|
|
41
41
|
main()
|
ttfquery-2.0.1a1/pyproject.toml
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=61.0"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "TTFQuery"
|
|
7
|
-
dynamic = ["version"]
|
|
8
|
-
description = "FontTools-based package for querying system fonts"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
license = { file = "license.txt" }
|
|
11
|
-
authors = [
|
|
12
|
-
{ name = "Mike C. Fletcher", email = "mcfletch@users.sourceforge.net" },
|
|
13
|
-
]
|
|
14
|
-
requires-python = ">=3.7"
|
|
15
|
-
dependencies = [
|
|
16
|
-
"fonttools",
|
|
17
|
-
"numpy",
|
|
18
|
-
]
|
|
19
|
-
keywords = [
|
|
20
|
-
"fonttools",
|
|
21
|
-
"ttf",
|
|
22
|
-
"truetype",
|
|
23
|
-
"outline",
|
|
24
|
-
"font",
|
|
25
|
-
"curve",
|
|
26
|
-
"system fonts",
|
|
27
|
-
]
|
|
28
|
-
classifiers = [
|
|
29
|
-
"Programming Language :: Python",
|
|
30
|
-
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
-
"Intended Audience :: Developers",
|
|
32
|
-
"Operating System :: OS Independent",
|
|
33
|
-
"Topic :: Multimedia :: Graphics",
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
[project.urls]
|
|
37
|
-
Homepage = "http://ttfquery.sourceforge.net/"
|
|
38
|
-
|
|
39
|
-
[project.optional-dependencies]
|
|
40
|
-
test = [
|
|
41
|
-
"pytest",
|
|
42
|
-
"pytest-cov",
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
[project.scripts]
|
|
46
|
-
ttffiles = "ttfquery.ttffiles:main"
|
|
47
|
-
ttffamily = "ttfquery.ttffamily:main"
|
|
48
|
-
ttfgroups = "ttfquery.ttfgroups:main"
|
|
49
|
-
ttfmetadata = "ttfquery.ttfmetadata:main"
|
|
50
|
-
|
|
51
|
-
[tool.setuptools]
|
|
52
|
-
packages = ["ttfquery"]
|
|
53
|
-
|
|
54
|
-
[tool.setuptools.dynamic]
|
|
55
|
-
version = { attr = "ttfquery.__version__" }
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from __future__ import print_function
|
|
2
|
-
from ttfquery import describe, findsystem
|
|
3
|
-
import pytest
|
|
4
|
-
import sys, glob, unittest
|
|
5
|
-
|
|
6
|
-
class TestDescribe(unittest.TestCase):
|
|
7
|
-
def test_describe_system_fonts(self):
|
|
8
|
-
for fontfile in list(findsystem.findFonts())[:100]:
|
|
9
|
-
try:
|
|
10
|
-
font = describe.openFont(fontfile)
|
|
11
|
-
except Exception as err:
|
|
12
|
-
err.args += ('Error opening font', font)
|
|
13
|
-
raise
|
|
14
|
-
else:
|
|
15
|
-
short = describe.shortName( font )
|
|
16
|
-
assert short, "Null name for font %s"%(fontfile,)
|
|
17
|
-
family = describe.family( font )
|
|
18
|
-
assert len(family)==2, family
|
|
19
|
-
modifiers = describe.modifiers( font )
|
|
20
|
-
assert describe.weightName(modifiers[0])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|