TTFQuery 2.0.1a1__tar.gz → 2.1.1__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.1}/PKG-INFO +11 -4
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/README.md +2 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/PKG-INFO +11 -4
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/SOURCES.txt +1 -0
- ttfquery-2.1.1/pyproject.toml +124 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/setup.py +4 -4
- ttfquery-2.1.1/tests/test_describe.py +191 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/tests/test_findsystem_linux.py +3 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/tests/test_findsystem_win32.py +4 -1
- ttfquery-2.1.1/tests/test_glyphquery.py +451 -0
- ttfquery-2.1.1/tests/test_registry.py +168 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/__init__.py +1 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/_scriptregistry.py +3 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/describe.py +109 -57
- ttfquery-2.1.1/ttfquery/errors.py +31 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/findsystem.py +24 -21
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/glyph.py +86 -21
- ttfquery-2.1.1/ttfquery/glyphquery.py +234 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/guessdescription.py +5 -3
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/scriptregistry.py +6 -4
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/ttffamily.py +1 -1
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/ttffiles.py +82 -50
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/ttfquery/ttfgroups.py +9 -6
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/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/tests/test_glyphquery.py +0 -45
- ttfquery-2.0.1a1/tests/test_registry.py +0 -59
- ttfquery-2.0.1a1/ttfquery/glyphquery.py +0 -90
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/MANIFEST.in +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/dependency_links.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/entry_points.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/requires.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/TTFQuery.egg-info/top_level.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/license.txt +0 -0
- {ttfquery-2.0.1a1 → ttfquery-2.1.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TTFQuery
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
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
|
|
@@ -73,7 +79,8 @@ TTFQuery builds on the FontTools package to allow the Python programmer to accom
|
|
|
73
79
|
* abstract family type
|
|
74
80
|
* proper font name
|
|
75
81
|
* glyph outlines
|
|
76
|
-
* build simple metadata registries for run-time font matching
|
|
82
|
+
* build simple metadata registries for run-time font matching, holding the
|
|
83
|
+
fonts text can be laid out with and reporting the files that cannot
|
|
77
84
|
|
|
78
85
|
With these functionalities, it is possible to readily create OpenGL solid-text
|
|
79
86
|
rendering libraries which can accept abstract font-family names as font
|
|
@@ -9,7 +9,8 @@ TTFQuery builds on the FontTools package to allow the Python programmer to accom
|
|
|
9
9
|
* abstract family type
|
|
10
10
|
* proper font name
|
|
11
11
|
* glyph outlines
|
|
12
|
-
* build simple metadata registries for run-time font matching
|
|
12
|
+
* build simple metadata registries for run-time font matching, holding the
|
|
13
|
+
fonts text can be laid out with and reporting the files that cannot
|
|
13
14
|
|
|
14
15
|
With these functionalities, it is possible to readily create OpenGL solid-text
|
|
15
16
|
rendering libraries which can accept abstract font-family names as font
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TTFQuery
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
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
|
|
@@ -73,7 +79,8 @@ TTFQuery builds on the FontTools package to allow the Python programmer to accom
|
|
|
73
79
|
* abstract family type
|
|
74
80
|
* proper font name
|
|
75
81
|
* glyph outlines
|
|
76
|
-
* build simple metadata registries for run-time font matching
|
|
82
|
+
* build simple metadata registries for run-time font matching, holding the
|
|
83
|
+
fonts text can be laid out with and reporting the files that cannot
|
|
77
84
|
|
|
78
85
|
With these functionalities, it is possible to readily create OpenGL solid-text
|
|
79
86
|
rendering libraries which can accept abstract font-family names as font
|
|
@@ -0,0 +1,124 @@
|
|
|
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.openglcontext-checks]
|
|
75
|
+
# The OGC rules (openglcontext-checks) this project is clean of, held by
|
|
76
|
+
# the workspace preflight. The others join as the project reaches zero of
|
|
77
|
+
# each; the counts are in openglcontext/plans/DEFECT-PREVENTION.md.
|
|
78
|
+
select = ["OGC121", "OGC131", "OGC141", "OGC201", "OGC221"]
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
select = [
|
|
82
|
+
"E", "W", "F", "B", "PGH003", "PGH004", "PLE0604", "PLE0605",
|
|
83
|
+
# A noqa that silences nothing, and an exception swallowed with no trace
|
|
84
|
+
# or caught wider than what can be raised.
|
|
85
|
+
"RUF100", "S110", "S112", "E722", "TRY400", "BLE001",
|
|
86
|
+
# Parameters nothing reads, and datetimes with no time zone.
|
|
87
|
+
"ARG", "DTZ",
|
|
88
|
+
# A mutable class attribute, an import inside a function, and a private
|
|
89
|
+
# name reached from another module.
|
|
90
|
+
"RUF012", "PLC0415", "SLF001",
|
|
91
|
+
# exec, eval, unpickling, tar extraction without a filter, and URL
|
|
92
|
+
# opening of any scheme.
|
|
93
|
+
"S102", "S307", "S301", "S202", "S310",
|
|
94
|
+
# `X | Y` for unions where the floor allows it, and the builtin generics
|
|
95
|
+
# (`dict[str, int]`) rather than their `typing` aliases.
|
|
96
|
+
"UP007", "UP006", "UP035",
|
|
97
|
+
]
|
|
98
|
+
# `_name` as well as `_`: an underscore prefix is how Python says a name is
|
|
99
|
+
# bound but deliberately unused.
|
|
100
|
+
dummy-variable-rgx = "^(_[a-zA-Z0-9_]*|err)$"
|
|
101
|
+
ignore = [
|
|
102
|
+
'E501', # long lines, kept readable by hand
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
# The package's own declarations, checked as a consumer's checker reads them.
|
|
106
|
+
# `check_untyped_defs` rather than `disallow_untyped_defs`: this package is
|
|
107
|
+
# older than annotations, and its bodies being checked is the half that finds
|
|
108
|
+
# defects -- the other half is a job of its own, tracked as one.
|
|
109
|
+
[tool.mypy]
|
|
110
|
+
# Named here so that `mypy` with no arguments checks the package: the tox
|
|
111
|
+
# environment and a developer's bare `mypy` are then the same run.
|
|
112
|
+
files = ["ttfquery"]
|
|
113
|
+
python_version = "3.12"
|
|
114
|
+
check_untyped_defs = true
|
|
115
|
+
warn_unused_ignores = true
|
|
116
|
+
ignore_missing_imports = true
|
|
117
|
+
|
|
118
|
+
# `findsystem` reads the Windows font directories out of the registry, and
|
|
119
|
+
# `winreg` is a module Linux does not have. Checked as Windows sees it in a
|
|
120
|
+
# second run -- see tools/preflight.toml -- so this keeps the Linux run from
|
|
121
|
+
# reporting nine absent names as defects.
|
|
122
|
+
[[tool.mypy.overrides]]
|
|
123
|
+
module = "ttfquery.findsystem"
|
|
124
|
+
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,191 @@
|
|
|
1
|
+
from __future__ import print_function
|
|
2
|
+
from types import SimpleNamespace
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
from fontTools import ttLib
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from ttfquery import describe, findsystem, glyphquery
|
|
9
|
+
|
|
10
|
+
from builtfonts import built_open, glyphNameFor, withSubtables
|
|
11
|
+
|
|
12
|
+
class TestDescribe(unittest.TestCase):
|
|
13
|
+
def test_describe_system_fonts(self):
|
|
14
|
+
for fontfile in list(findsystem.findFonts())[:100]:
|
|
15
|
+
try:
|
|
16
|
+
font = describe.openFont(fontfile)
|
|
17
|
+
except Exception as err:
|
|
18
|
+
err.args += ('Error opening font', fontfile)
|
|
19
|
+
raise
|
|
20
|
+
else:
|
|
21
|
+
short = describe.shortName( font )
|
|
22
|
+
assert short, "Null name for font %s"%(fontfile,)
|
|
23
|
+
family = describe.family( font )
|
|
24
|
+
assert len(family)==2, family
|
|
25
|
+
modifiers = describe.modifiers( font )
|
|
26
|
+
assert describe.weightName(modifiers[0])
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def a_named_font(name, family, typographic=None):
|
|
30
|
+
"""A stand-in font whose name table holds `name` and `family` records,
|
|
31
|
+
and a typographic family record where `typographic` is given."""
|
|
32
|
+
records = [
|
|
33
|
+
SimpleNamespace(nameID=describe.FONT_SPECIFIER_NAME_ID, string=name),
|
|
34
|
+
SimpleNamespace(nameID=describe.FONT_SPECIFIER_FAMILY_ID, string=family),
|
|
35
|
+
]
|
|
36
|
+
if typographic is not None:
|
|
37
|
+
records.append(SimpleNamespace(
|
|
38
|
+
nameID=describe.FONT_TYPOGRAPHIC_FAMILY_ID, string=typographic))
|
|
39
|
+
return {'name': SimpleNamespace(names=records)}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class TestTheNameIsText:
|
|
43
|
+
"""`shortName` answers what the font calls itself, as text.
|
|
44
|
+
|
|
45
|
+
A name record is bytes in one of two encodings, and answering those bytes
|
|
46
|
+
put `b'Open Sans'` into every message that named a font and left the font
|
|
47
|
+
registry decoding what this had just encoded.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def a_font(self):
|
|
51
|
+
for path in findsystem.findFonts():
|
|
52
|
+
try:
|
|
53
|
+
return describe.openFont(path)
|
|
54
|
+
except (OSError, ttLib.TTLibError):
|
|
55
|
+
continue
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
def test_both_halves_are_strings(self):
|
|
59
|
+
font = self.a_font()
|
|
60
|
+
if font is None:
|
|
61
|
+
pytest.skip('no readable font on this machine')
|
|
62
|
+
name, family = describe.shortName(font)
|
|
63
|
+
assert isinstance(name, str), repr(name)
|
|
64
|
+
assert isinstance(family, str), repr(family)
|
|
65
|
+
|
|
66
|
+
def test_a_two_byte_record_is_read_as_utf_16(self):
|
|
67
|
+
font = a_named_font(
|
|
68
|
+
'Ångstrom Bold'.encode('utf-16-be'), 'Ångstrom'.encode('utf-16-be'),
|
|
69
|
+
)
|
|
70
|
+
assert describe.shortName(font) == ('Ångstrom Bold', 'Ångstrom')
|
|
71
|
+
|
|
72
|
+
def test_a_single_byte_record_is_read_as_latin_1(self):
|
|
73
|
+
font = a_named_font(b'Open Sans Bold', b'Open Sans')
|
|
74
|
+
assert describe.shortName(font) == ('Open Sans Bold', 'Open Sans')
|
|
75
|
+
|
|
76
|
+
def test_text_is_left_as_it_is(self):
|
|
77
|
+
font = a_named_font('Open Sans Bold', 'Open Sans')
|
|
78
|
+
assert describe.shortName(font) == ('Open Sans Bold', 'Open Sans')
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class TestTheEncodingIsAUnicodeOne:
|
|
82
|
+
"""Which cmap sub-table a character is looked up in.
|
|
83
|
+
|
|
84
|
+
A character reaches the sub-table as `ord(char)`, a Unicode code point, so
|
|
85
|
+
the sub-table that answers about the character asked for is a Unicode one.
|
|
86
|
+
A Macintosh or symbol sub-table numbers its characters its own way and
|
|
87
|
+
answers with whichever glyph it keeps at that number, which is a different
|
|
88
|
+
character and, in the fonts where it bites, a different glyph.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def a_font(self, *encodings, holds=None):
|
|
92
|
+
"""A font carrying these cmap sub-tables, in this order
|
|
93
|
+
|
|
94
|
+
holds -- (platformID, platEncID) to the character whose glyph that
|
|
95
|
+
sub-table is to keep at code point 97, where it is meant to
|
|
96
|
+
disagree with the others. Every sub-table holds `a`'s glyph there
|
|
97
|
+
by default, so which sub-table a lookup read shows up in the glyph
|
|
98
|
+
name it answers with.
|
|
99
|
+
"""
|
|
100
|
+
holds = holds or {}
|
|
101
|
+
font = built_open({'a': 500, 'b': 500, 'c': 500, 'd': 500})
|
|
102
|
+
return withSubtables(font, {
|
|
103
|
+
encoding: {ord('a'): glyphNameFor(holds.get(encoding, 'a'))}
|
|
104
|
+
for encoding in encodings
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
def test_a_unicode_subtable_wins_over_a_macintosh_one(self):
|
|
108
|
+
font = self.a_font((1, 0), (3, 1))
|
|
109
|
+
assert describe.guessEncoding(font) == (3, 1)
|
|
110
|
+
|
|
111
|
+
def test_the_order_in_the_file_does_not_decide(self):
|
|
112
|
+
"""A font that carries its Macintosh sub-table first is read the same"""
|
|
113
|
+
assert describe.guessEncoding(self.a_font((3, 1), (1, 0))) == \
|
|
114
|
+
describe.guessEncoding(self.a_font((1, 0), (3, 1)))
|
|
115
|
+
|
|
116
|
+
def test_a_symbol_subtable_is_not_a_unicode_one(self):
|
|
117
|
+
"""Encoding 0 on platform 3 is the symbol range, not the BMP"""
|
|
118
|
+
font = self.a_font((3, 0), (0, 3))
|
|
119
|
+
assert describe.guessEncoding(font) == (0, 3)
|
|
120
|
+
|
|
121
|
+
def test_the_whole_repertoire_is_preferred_to_the_bmp(self):
|
|
122
|
+
font = self.a_font((3, 1), (3, 10))
|
|
123
|
+
assert describe.guessEncoding(font) == (3, 10)
|
|
124
|
+
font = self.a_font((0, 3), (0, 4))
|
|
125
|
+
assert describe.guessEncoding(font) == (0, 4)
|
|
126
|
+
|
|
127
|
+
def test_every_preference_is_a_unicode_encoding(self):
|
|
128
|
+
for encoding in describe.UNICODE_ENCODINGS:
|
|
129
|
+
assert encoding[0] in (0, 3), encoding
|
|
130
|
+
if encoding[0] == 3:
|
|
131
|
+
assert encoding[1] in (1, 10), encoding
|
|
132
|
+
|
|
133
|
+
def test_each_preference_is_chosen_over_a_macintosh_subtable(self):
|
|
134
|
+
for encoding in describe.UNICODE_ENCODINGS:
|
|
135
|
+
font = self.a_font((1, 0), encoding)
|
|
136
|
+
assert describe.guessEncoding(font) == encoding, encoding
|
|
137
|
+
|
|
138
|
+
def test_a_font_with_no_unicode_subtable_answers_with_what_it_has(self):
|
|
139
|
+
"""A symbol font keeps its glyphs at code points of its own"""
|
|
140
|
+
font = self.a_font((3, 0), (1, 0))
|
|
141
|
+
assert describe.guessEncoding(font) == (3, 0)
|
|
142
|
+
|
|
143
|
+
def test_the_glyph_read_is_the_one_the_unicode_subtable_names(self):
|
|
144
|
+
"""The reading this preference exists for
|
|
145
|
+
|
|
146
|
+
The two sub-tables disagree about what lives at 97: the Macintosh one
|
|
147
|
+
answers with another character's glyph, and the Unicode one with `a`.
|
|
148
|
+
"""
|
|
149
|
+
font = self.a_font((1, 0), (3, 1), holds={(1, 0): 'd'})
|
|
150
|
+
assert glyphquery.explicitGlyph(font, 'a') == glyphNameFor('a')
|
|
151
|
+
assert glyphquery.width(font, glyphquery.explicitGlyph(font, 'a')) == 500
|
|
152
|
+
|
|
153
|
+
def test_an_encoding_the_caller_names_is_used_as_given(self):
|
|
154
|
+
"""A caller who names a sub-table gets that sub-table"""
|
|
155
|
+
font = self.a_font((1, 0), (3, 1), holds={(1, 0): 'd'})
|
|
156
|
+
assert describe.guessEncoding(font, (1, 0)) == (1, 0)
|
|
157
|
+
assert glyphquery.explicitGlyph(font, 'a', (1, 0)) == glyphNameFor('d')
|
|
158
|
+
|
|
159
|
+
def test_a_platform_the_caller_names_is_searched(self):
|
|
160
|
+
font = self.a_font((1, 0), (3, 1))
|
|
161
|
+
assert describe.guessEncoding(font, 3) == (3, 1)
|
|
162
|
+
assert describe.guessEncoding(font, (1,)) == (1, 0)
|
|
163
|
+
|
|
164
|
+
def test_an_encoding_the_font_has_not_got_says_so(self):
|
|
165
|
+
font = self.a_font((3, 1))
|
|
166
|
+
for given, wanted in (((1, 0), 'does not appear'), (1, 'platformID==1')):
|
|
167
|
+
try:
|
|
168
|
+
describe.guessEncoding(font, given)
|
|
169
|
+
except ValueError as err:
|
|
170
|
+
assert wanted in str(err), err
|
|
171
|
+
else:
|
|
172
|
+
raise AssertionError('%r was accepted' % (given,))
|
|
173
|
+
|
|
174
|
+
def test_a_font_with_no_subtables_at_all_says_so(self):
|
|
175
|
+
font = withSubtables(built_open({'a': 500}), {})
|
|
176
|
+
try:
|
|
177
|
+
describe.guessEncoding(font)
|
|
178
|
+
except ValueError as err:
|
|
179
|
+
assert 'no encoding tables' in str(err), err
|
|
180
|
+
else:
|
|
181
|
+
raise AssertionError('a font with no cmap sub-table was accepted')
|
|
182
|
+
class TestTheFamily:
|
|
183
|
+
"""`shortName`'s family is the typographic family where the font names one"""
|
|
184
|
+
|
|
185
|
+
def test_a_weight_outside_the_four_styles_joins_its_family(self):
|
|
186
|
+
font = a_named_font('Open Sans Light', 'Open Sans Light', 'Open Sans')
|
|
187
|
+
assert describe.shortName(font) == ('Open Sans Light', 'Open Sans')
|
|
188
|
+
|
|
189
|
+
def test_without_one_it_is_the_legacy_family(self):
|
|
190
|
+
font = a_named_font('Open Sans Bold', 'Open Sans')
|
|
191
|
+
assert describe.shortName(font) == ('Open Sans Bold', '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):
|