fonttools 4.55.4__cp313-cp313-musllinux_1_2_aarch64.whl → 4.61.1__cp313-cp313-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fontTools/__init__.py +1 -1
- fontTools/annotations.py +30 -0
- fontTools/cffLib/CFF2ToCFF.py +65 -10
- fontTools/cffLib/__init__.py +61 -26
- fontTools/cffLib/specializer.py +4 -1
- fontTools/cffLib/transforms.py +11 -6
- fontTools/config/__init__.py +15 -0
- fontTools/cu2qu/cu2qu.c +6567 -5579
- fontTools/cu2qu/cu2qu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/cu2qu/cu2qu.py +36 -4
- fontTools/cu2qu/ufo.py +14 -0
- fontTools/designspaceLib/__init__.py +8 -3
- fontTools/designspaceLib/statNames.py +14 -7
- fontTools/feaLib/ast.py +24 -15
- fontTools/feaLib/builder.py +139 -66
- fontTools/feaLib/error.py +1 -1
- fontTools/feaLib/lexer.c +7038 -7995
- fontTools/feaLib/lexer.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/feaLib/parser.py +75 -40
- fontTools/feaLib/variableScalar.py +6 -1
- fontTools/fontBuilder.py +50 -44
- fontTools/merge/__init__.py +1 -1
- fontTools/merge/cmap.py +33 -1
- fontTools/merge/tables.py +12 -1
- fontTools/misc/bezierTools.c +14913 -17013
- fontTools/misc/bezierTools.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/misc/bezierTools.py +4 -1
- fontTools/misc/configTools.py +3 -1
- fontTools/misc/enumTools.py +23 -0
- fontTools/misc/etree.py +4 -27
- fontTools/misc/filesystem/__init__.py +68 -0
- fontTools/misc/filesystem/_base.py +134 -0
- fontTools/misc/filesystem/_copy.py +45 -0
- fontTools/misc/filesystem/_errors.py +54 -0
- fontTools/misc/filesystem/_info.py +75 -0
- fontTools/misc/filesystem/_osfs.py +164 -0
- fontTools/misc/filesystem/_path.py +67 -0
- fontTools/misc/filesystem/_subfs.py +92 -0
- fontTools/misc/filesystem/_tempfs.py +34 -0
- fontTools/misc/filesystem/_tools.py +34 -0
- fontTools/misc/filesystem/_walk.py +55 -0
- fontTools/misc/filesystem/_zipfs.py +204 -0
- fontTools/misc/fixedTools.py +1 -1
- fontTools/misc/loggingTools.py +1 -1
- fontTools/misc/psCharStrings.py +17 -2
- fontTools/misc/sstruct.py +2 -6
- fontTools/misc/symfont.py +6 -8
- fontTools/misc/testTools.py +5 -1
- fontTools/misc/textTools.py +4 -2
- fontTools/misc/visitor.py +32 -16
- fontTools/misc/xmlWriter.py +44 -8
- fontTools/mtiLib/__init__.py +1 -3
- fontTools/otlLib/builder.py +402 -155
- fontTools/otlLib/optimize/gpos.py +49 -63
- fontTools/pens/filterPen.py +218 -26
- fontTools/pens/momentsPen.c +5514 -5584
- fontTools/pens/momentsPen.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/pens/pointPen.py +61 -18
- fontTools/pens/roundingPen.py +2 -2
- fontTools/pens/t2CharStringPen.py +31 -11
- fontTools/qu2cu/qu2cu.c +6581 -6168
- fontTools/qu2cu/qu2cu.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/subset/__init__.py +283 -25
- fontTools/subset/svg.py +2 -3
- fontTools/ttLib/__init__.py +4 -0
- fontTools/ttLib/__main__.py +47 -8
- fontTools/ttLib/removeOverlaps.py +7 -5
- fontTools/ttLib/reorderGlyphs.py +8 -7
- fontTools/ttLib/sfnt.py +11 -9
- fontTools/ttLib/tables/D__e_b_g.py +20 -2
- fontTools/ttLib/tables/G_V_A_R_.py +5 -0
- fontTools/ttLib/tables/S__i_l_f.py +2 -2
- fontTools/ttLib/tables/T_S_I__0.py +14 -3
- fontTools/ttLib/tables/T_S_I__1.py +2 -5
- fontTools/ttLib/tables/T_S_I__5.py +18 -7
- fontTools/ttLib/tables/__init__.py +1 -0
- fontTools/ttLib/tables/_a_v_a_r.py +12 -3
- fontTools/ttLib/tables/_c_m_a_p.py +20 -7
- fontTools/ttLib/tables/_c_v_t.py +3 -2
- fontTools/ttLib/tables/_f_p_g_m.py +3 -1
- fontTools/ttLib/tables/_g_l_y_f.py +45 -21
- fontTools/ttLib/tables/_g_v_a_r.py +67 -19
- fontTools/ttLib/tables/_h_d_m_x.py +4 -4
- fontTools/ttLib/tables/_h_m_t_x.py +7 -3
- fontTools/ttLib/tables/_l_o_c_a.py +2 -2
- fontTools/ttLib/tables/_n_a_m_e.py +11 -6
- fontTools/ttLib/tables/_p_o_s_t.py +9 -7
- fontTools/ttLib/tables/otBase.py +5 -12
- fontTools/ttLib/tables/otConverters.py +5 -2
- fontTools/ttLib/tables/otData.py +1 -1
- fontTools/ttLib/tables/otTables.py +33 -30
- fontTools/ttLib/tables/otTraverse.py +2 -1
- fontTools/ttLib/tables/sbixStrike.py +3 -3
- fontTools/ttLib/ttFont.py +666 -120
- fontTools/ttLib/ttGlyphSet.py +0 -10
- fontTools/ttLib/woff2.py +10 -13
- fontTools/ttx.py +13 -1
- fontTools/ufoLib/__init__.py +300 -202
- fontTools/ufoLib/converters.py +103 -30
- fontTools/ufoLib/errors.py +8 -0
- fontTools/ufoLib/etree.py +1 -1
- fontTools/ufoLib/filenames.py +171 -106
- fontTools/ufoLib/glifLib.py +303 -205
- fontTools/ufoLib/kerning.py +98 -48
- fontTools/ufoLib/utils.py +46 -15
- fontTools/ufoLib/validators.py +121 -99
- fontTools/unicodedata/Blocks.py +35 -20
- fontTools/unicodedata/Mirrored.py +446 -0
- fontTools/unicodedata/ScriptExtensions.py +63 -37
- fontTools/unicodedata/Scripts.py +173 -152
- fontTools/unicodedata/__init__.py +10 -2
- fontTools/varLib/__init__.py +198 -109
- fontTools/varLib/avar/__init__.py +0 -0
- fontTools/varLib/avar/__main__.py +72 -0
- fontTools/varLib/avar/build.py +79 -0
- fontTools/varLib/avar/map.py +108 -0
- fontTools/varLib/avar/plan.py +1004 -0
- fontTools/varLib/{avar.py → avar/unbuild.py} +70 -59
- fontTools/varLib/avarPlanner.py +3 -999
- fontTools/varLib/featureVars.py +21 -7
- fontTools/varLib/hvar.py +113 -0
- fontTools/varLib/instancer/__init__.py +180 -65
- fontTools/varLib/interpolatableHelpers.py +3 -0
- fontTools/varLib/iup.c +7564 -6903
- fontTools/varLib/iup.cpython-313-aarch64-linux-musl.so +0 -0
- fontTools/varLib/models.py +17 -2
- fontTools/varLib/mutator.py +11 -0
- fontTools/varLib/varStore.py +10 -38
- fontTools/voltLib/__main__.py +206 -0
- fontTools/voltLib/ast.py +4 -0
- fontTools/voltLib/parser.py +16 -8
- fontTools/voltLib/voltToFea.py +347 -166
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/METADATA +269 -1410
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/RECORD +318 -294
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/WHEEL +1 -1
- fonttools-4.61.1.dist-info/licenses/LICENSE.external +388 -0
- {fonttools-4.55.4.data → fonttools-4.61.1.data}/data/share/man/man1/ttx.1 +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/entry_points.txt +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info/licenses}/LICENSE +0 -0
- {fonttools-4.55.4.dist-info → fonttools-4.61.1.dist-info}/top_level.txt +0 -0
|
Binary file
|
fontTools/cu2qu/cu2qu.py
CHANGED
|
@@ -37,7 +37,7 @@ NAN = float("NaN")
|
|
|
37
37
|
@cython.cfunc
|
|
38
38
|
@cython.inline
|
|
39
39
|
@cython.returns(cython.double)
|
|
40
|
-
@cython.locals(v1=cython.complex, v2=cython.complex)
|
|
40
|
+
@cython.locals(v1=cython.complex, v2=cython.complex, result=cython.double)
|
|
41
41
|
def dot(v1, v2):
|
|
42
42
|
"""Return the dot product of two vectors.
|
|
43
43
|
|
|
@@ -48,7 +48,33 @@ def dot(v1, v2):
|
|
|
48
48
|
Returns:
|
|
49
49
|
double: Dot product.
|
|
50
50
|
"""
|
|
51
|
-
|
|
51
|
+
result = (v1 * v2.conjugate()).real
|
|
52
|
+
# When vectors are perpendicular (i.e. dot product is 0), the above expression may
|
|
53
|
+
# yield slightly different results when running in pure Python vs C/Cython,
|
|
54
|
+
# both of which are correct within IEEE-754 floating-point precision.
|
|
55
|
+
# It's probably due to the different order of operations and roundings in each
|
|
56
|
+
# implementation. Because we are using the result in a denominator and catching
|
|
57
|
+
# ZeroDivisionError (see `calc_intersect`), it's best to normalize the result here.
|
|
58
|
+
if abs(result) < 1e-15:
|
|
59
|
+
result = 0.0
|
|
60
|
+
return result
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@cython.cfunc
|
|
64
|
+
@cython.locals(z=cython.complex, den=cython.double)
|
|
65
|
+
@cython.locals(zr=cython.double, zi=cython.double)
|
|
66
|
+
def _complex_div_by_real(z, den):
|
|
67
|
+
"""Divide complex by real using Python's method (two separate divisions).
|
|
68
|
+
|
|
69
|
+
This ensures bit-exact compatibility with Python's complex division,
|
|
70
|
+
avoiding C's multiply-by-reciprocal optimization that can cause 1 ULP differences
|
|
71
|
+
on some platforms/compilers (e.g. clang on macOS arm64).
|
|
72
|
+
|
|
73
|
+
https://github.com/fonttools/fonttools/issues/3928
|
|
74
|
+
"""
|
|
75
|
+
zr = z.real
|
|
76
|
+
zi = z.imag
|
|
77
|
+
return complex(zr / den, zi / den)
|
|
52
78
|
|
|
53
79
|
|
|
54
80
|
@cython.cfunc
|
|
@@ -59,8 +85,8 @@ def dot(v1, v2):
|
|
|
59
85
|
)
|
|
60
86
|
def calc_cubic_points(a, b, c, d):
|
|
61
87
|
_1 = d
|
|
62
|
-
_2 = (c
|
|
63
|
-
_3 = (b + c
|
|
88
|
+
_2 = _complex_div_by_real(c, 3.0) + d
|
|
89
|
+
_3 = _complex_div_by_real(b + c, 3.0) + _2
|
|
64
90
|
_4 = a + d + c + b
|
|
65
91
|
return _1, _2, _3, _4
|
|
66
92
|
|
|
@@ -273,6 +299,12 @@ def calc_intersect(a, b, c, d):
|
|
|
273
299
|
try:
|
|
274
300
|
h = dot(p, a - c) / dot(p, cd)
|
|
275
301
|
except ZeroDivisionError:
|
|
302
|
+
# if 3 or 4 points are equal, we do have an intersection despite the zero-div:
|
|
303
|
+
# return one of the off-curves so that the algorithm can attempt a one-curve
|
|
304
|
+
# solution if it's within tolerance:
|
|
305
|
+
# https://github.com/linebender/kurbo/pull/484
|
|
306
|
+
if b == c and (a == b or c == d):
|
|
307
|
+
return b
|
|
276
308
|
return complex(NAN, NAN)
|
|
277
309
|
return c + cd * h
|
|
278
310
|
|
fontTools/cu2qu/ufo.py
CHANGED
|
@@ -165,9 +165,19 @@ def _glyphs_to_quadratic(glyphs, max_err, reverse_direction, stats, all_quadrati
|
|
|
165
165
|
"""Do the actual conversion of a set of compatible glyphs, after arguments
|
|
166
166
|
have been set up.
|
|
167
167
|
|
|
168
|
+
Empty glyphs (without contours) are ignored and passed through unchanged.
|
|
169
|
+
|
|
168
170
|
Return True if the glyphs were modified, else return False.
|
|
169
171
|
"""
|
|
170
172
|
|
|
173
|
+
# Skip empty glyphs (with zero contours)
|
|
174
|
+
non_empty_indices = [i for i, g in enumerate(glyphs) if len(g) > 0]
|
|
175
|
+
if not non_empty_indices:
|
|
176
|
+
return False
|
|
177
|
+
|
|
178
|
+
glyphs = [glyphs[i] for i in non_empty_indices]
|
|
179
|
+
max_err = [max_err[i] for i in non_empty_indices]
|
|
180
|
+
|
|
171
181
|
try:
|
|
172
182
|
segments_by_location = zip(*[_get_segments(g) for g in glyphs])
|
|
173
183
|
except UnequalZipLengthsError:
|
|
@@ -212,6 +222,8 @@ def glyphs_to_quadratic(
|
|
|
212
222
|
compatibility. If this is not required, calling glyphs_to_quadratic with one
|
|
213
223
|
glyph at a time may yield slightly more optimized results.
|
|
214
224
|
|
|
225
|
+
Empty glyphs (without contours) are ignored and passed through unchanged.
|
|
226
|
+
|
|
215
227
|
Return True if glyphs were modified, else return False.
|
|
216
228
|
|
|
217
229
|
Raises IncompatibleGlyphsError if glyphs have non-interpolatable outlines.
|
|
@@ -250,6 +262,8 @@ def fonts_to_quadratic(
|
|
|
250
262
|
compatibility. If this is not required, calling fonts_to_quadratic with one
|
|
251
263
|
font at a time may yield slightly more optimized results.
|
|
252
264
|
|
|
265
|
+
Empty glyphs (without contours) are ignored and passed through unchanged.
|
|
266
|
+
|
|
253
267
|
Return the set of modified glyph names if any, else return an empty set.
|
|
254
268
|
|
|
255
269
|
By default, cu2qu stores the curve type in the fonts' lib, under a private
|
|
@@ -1323,6 +1323,11 @@ class VariableFontDescriptor(SimpleDescriptor):
|
|
|
1323
1323
|
in the document**. The file may or may not exist.
|
|
1324
1324
|
|
|
1325
1325
|
If not specified, the :attr:`name` will be used as a basename for the file.
|
|
1326
|
+
|
|
1327
|
+
.. note::
|
|
1328
|
+
This is intended to be a simple filename (basename or stem) only.
|
|
1329
|
+
Build tools will only use the basename component and ignore any
|
|
1330
|
+
directory separators for security reasons.
|
|
1326
1331
|
"""
|
|
1327
1332
|
self.axisSubsets: List[
|
|
1328
1333
|
Union[RangeAxisSubsetDescriptor, ValueAxisSubsetDescriptor]
|
|
@@ -1554,7 +1559,6 @@ class BaseDocWriter(object):
|
|
|
1554
1559
|
return ("%f" % num).rstrip("0").rstrip(".")
|
|
1555
1560
|
|
|
1556
1561
|
def _addRule(self, ruleObject):
|
|
1557
|
-
# if none of the conditions have minimum or maximum values, do not add the rule.
|
|
1558
1562
|
ruleElement = ET.Element("rule")
|
|
1559
1563
|
if ruleObject.name is not None:
|
|
1560
1564
|
ruleElement.attrib["name"] = ruleObject.name
|
|
@@ -1575,8 +1579,9 @@ class BaseDocWriter(object):
|
|
|
1575
1579
|
cond.get("maximum")
|
|
1576
1580
|
)
|
|
1577
1581
|
conditionsetElement.append(conditionElement)
|
|
1578
|
-
if
|
|
1579
|
-
|
|
1582
|
+
# Serialize the conditionset even if it is empty, as this is the
|
|
1583
|
+
# canonical way of defining a rule that is always true.
|
|
1584
|
+
ruleElement.append(conditionsetElement)
|
|
1580
1585
|
for sub in ruleObject.subs:
|
|
1581
1586
|
subElement = ET.Element("sub")
|
|
1582
1587
|
subElement.attrib["name"] = sub[0]
|
|
@@ -12,14 +12,13 @@ instance:
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
14
|
from dataclasses import dataclass
|
|
15
|
-
from typing import Dict, Optional, Tuple, Union
|
|
15
|
+
from typing import Dict, Literal, Optional, Tuple, Union
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
18
|
from fontTools.designspaceLib import (
|
|
19
19
|
AxisDescriptor,
|
|
20
20
|
AxisLabelDescriptor,
|
|
21
21
|
DesignSpaceDocument,
|
|
22
|
-
DesignSpaceDocumentError,
|
|
23
22
|
DiscreteAxisDescriptor,
|
|
24
23
|
SimpleLocationDict,
|
|
25
24
|
SourceDescriptor,
|
|
@@ -27,9 +26,13 @@ from fontTools.designspaceLib import (
|
|
|
27
26
|
|
|
28
27
|
LOGGER = logging.getLogger(__name__)
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
RibbiStyleName = Union[
|
|
30
|
+
Literal["regular"],
|
|
31
|
+
Literal["bold"],
|
|
32
|
+
Literal["italic"],
|
|
33
|
+
Literal["bold italic"],
|
|
34
|
+
]
|
|
35
|
+
|
|
33
36
|
BOLD_ITALIC_TO_RIBBI_STYLE = {
|
|
34
37
|
(False, False): "regular",
|
|
35
38
|
(False, True): "italic",
|
|
@@ -46,7 +49,7 @@ class StatNames:
|
|
|
46
49
|
styleNames: Dict[str, str]
|
|
47
50
|
postScriptFontName: Optional[str]
|
|
48
51
|
styleMapFamilyNames: Dict[str, str]
|
|
49
|
-
styleMapStyleName: Optional[
|
|
52
|
+
styleMapStyleName: Optional[RibbiStyleName]
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
def getStatNames(
|
|
@@ -61,6 +64,10 @@ def getStatNames(
|
|
|
61
64
|
localized names will be empty (family and style names), or the name will be
|
|
62
65
|
None (PostScript name).
|
|
63
66
|
|
|
67
|
+
Note: this method does not consider info attached to the instance, like
|
|
68
|
+
family name. The user needs to override all names on an instance that STAT
|
|
69
|
+
information would compute differently than desired.
|
|
70
|
+
|
|
64
71
|
.. versionadded:: 5.0
|
|
65
72
|
"""
|
|
66
73
|
familyNames: Dict[str, str] = {}
|
|
@@ -201,7 +208,7 @@ def _getAxisLabelsForUserLocation(
|
|
|
201
208
|
|
|
202
209
|
def _getRibbiStyle(
|
|
203
210
|
self: DesignSpaceDocument, userLocation: SimpleLocationDict
|
|
204
|
-
) -> Tuple[
|
|
211
|
+
) -> Tuple[RibbiStyleName, SimpleLocationDict]:
|
|
205
212
|
"""Compute the RIBBI style name of the given user location,
|
|
206
213
|
return the location of the matching Regular in the RIBBI group.
|
|
207
214
|
|
fontTools/feaLib/ast.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import weakref
|
|
1
2
|
from fontTools.feaLib.error import FeatureLibError
|
|
2
3
|
from fontTools.feaLib.location import FeatureLibLocation
|
|
3
4
|
from fontTools.misc.encodingTools import getEncoding
|
|
@@ -382,8 +383,7 @@ class FeatureBlock(Block):
|
|
|
382
383
|
def build(self, builder):
|
|
383
384
|
"""Call the ``start_feature`` callback on the builder object, visit
|
|
384
385
|
all the statements in this feature, and then call ``end_feature``."""
|
|
385
|
-
|
|
386
|
-
builder.start_feature(self.location, self.name)
|
|
386
|
+
builder.start_feature(self.location, self.name, self.use_extension)
|
|
387
387
|
# language exclude_dflt statements modify builder.features_
|
|
388
388
|
# limit them to this block with temporary builder.features_
|
|
389
389
|
features = builder.features_
|
|
@@ -433,8 +433,7 @@ class LookupBlock(Block):
|
|
|
433
433
|
self.name, self.use_extension = name, use_extension
|
|
434
434
|
|
|
435
435
|
def build(self, builder):
|
|
436
|
-
|
|
437
|
-
builder.start_lookup_block(self.location, self.name)
|
|
436
|
+
builder.start_lookup_block(self.location, self.name, self.use_extension)
|
|
438
437
|
Block.build(self, builder)
|
|
439
438
|
builder.end_lookup_block()
|
|
440
439
|
|
|
@@ -531,7 +530,7 @@ class MarkClass(object):
|
|
|
531
530
|
def addDefinition(self, definition):
|
|
532
531
|
"""Add a :class:`MarkClassDefinition` statement to this mark class."""
|
|
533
532
|
assert isinstance(definition, MarkClassDefinition)
|
|
534
|
-
self.definitions.append(definition)
|
|
533
|
+
self.definitions.append(weakref.proxy(definition))
|
|
535
534
|
for glyph in definition.glyphSet():
|
|
536
535
|
if glyph in self.glyphs:
|
|
537
536
|
otherLoc = self.glyphs[glyph].location
|
|
@@ -721,7 +720,7 @@ class ChainContextPosStatement(Statement):
|
|
|
721
720
|
for i, lookup in enumerate(lookups):
|
|
722
721
|
if lookup:
|
|
723
722
|
try:
|
|
724
|
-
(
|
|
723
|
+
iter(lookup)
|
|
725
724
|
except TypeError:
|
|
726
725
|
self.lookups[i] = [lookup]
|
|
727
726
|
|
|
@@ -753,7 +752,7 @@ class ChainContextPosStatement(Statement):
|
|
|
753
752
|
if len(self.suffix):
|
|
754
753
|
res += " " + " ".join(map(asFea, self.suffix))
|
|
755
754
|
else:
|
|
756
|
-
res += " ".join(map(asFea, self.
|
|
755
|
+
res += " ".join(map(asFea, self.glyphs))
|
|
757
756
|
res += ";"
|
|
758
757
|
return res
|
|
759
758
|
|
|
@@ -779,7 +778,7 @@ class ChainContextSubstStatement(Statement):
|
|
|
779
778
|
for i, lookup in enumerate(lookups):
|
|
780
779
|
if lookup:
|
|
781
780
|
try:
|
|
782
|
-
(
|
|
781
|
+
iter(lookup)
|
|
783
782
|
except TypeError:
|
|
784
783
|
self.lookups[i] = [lookup]
|
|
785
784
|
|
|
@@ -811,7 +810,7 @@ class ChainContextSubstStatement(Statement):
|
|
|
811
810
|
if len(self.suffix):
|
|
812
811
|
res += " " + " ".join(map(asFea, self.suffix))
|
|
813
812
|
else:
|
|
814
|
-
res += " ".join(map(asFea, self.
|
|
813
|
+
res += " ".join(map(asFea, self.glyphs))
|
|
815
814
|
res += ";"
|
|
816
815
|
return res
|
|
817
816
|
|
|
@@ -1512,7 +1511,9 @@ class SinglePosStatement(Statement):
|
|
|
1512
1511
|
res += " ".join(map(asFea, self.prefix)) + " "
|
|
1513
1512
|
res += " ".join(
|
|
1514
1513
|
[
|
|
1515
|
-
asFea(x[0])
|
|
1514
|
+
asFea(x[0])
|
|
1515
|
+
+ "'"
|
|
1516
|
+
+ ((" " + x[1].asFea()) if x[1] is not None else "")
|
|
1516
1517
|
for x in self.pos
|
|
1517
1518
|
]
|
|
1518
1519
|
)
|
|
@@ -1520,7 +1521,10 @@ class SinglePosStatement(Statement):
|
|
|
1520
1521
|
res += " " + " ".join(map(asFea, self.suffix))
|
|
1521
1522
|
else:
|
|
1522
1523
|
res += " ".join(
|
|
1523
|
-
[
|
|
1524
|
+
[
|
|
1525
|
+
asFea(x[0]) + " " + (x[1].asFea() if x[1] is not None else "")
|
|
1526
|
+
for x in self.pos
|
|
1527
|
+
]
|
|
1524
1528
|
)
|
|
1525
1529
|
res += ";"
|
|
1526
1530
|
return res
|
|
@@ -1828,15 +1832,16 @@ class BaseAxis(Statement):
|
|
|
1828
1832
|
"""An axis definition, being either a ``VertAxis.BaseTagList/BaseScriptList``
|
|
1829
1833
|
pair or a ``HorizAxis.BaseTagList/BaseScriptList`` pair."""
|
|
1830
1834
|
|
|
1831
|
-
def __init__(self, bases, scripts, vertical, location=None):
|
|
1835
|
+
def __init__(self, bases, scripts, vertical, minmax=None, location=None):
|
|
1832
1836
|
Statement.__init__(self, location)
|
|
1833
1837
|
self.bases = bases #: A list of baseline tag names as strings
|
|
1834
1838
|
self.scripts = scripts #: A list of script record tuplets (script tag, default baseline tag, base coordinate)
|
|
1835
1839
|
self.vertical = vertical #: Boolean; VertAxis if True, HorizAxis if False
|
|
1840
|
+
self.minmax = [] #: A set of minmax record
|
|
1836
1841
|
|
|
1837
1842
|
def build(self, builder):
|
|
1838
1843
|
"""Calls the builder object's ``set_base_axis`` callback."""
|
|
1839
|
-
builder.set_base_axis(self.bases, self.scripts, self.vertical)
|
|
1844
|
+
builder.set_base_axis(self.bases, self.scripts, self.vertical, self.minmax)
|
|
1840
1845
|
|
|
1841
1846
|
def asFea(self, indent=""):
|
|
1842
1847
|
direction = "Vert" if self.vertical else "Horiz"
|
|
@@ -1844,9 +1849,13 @@ class BaseAxis(Statement):
|
|
|
1844
1849
|
"{} {} {}".format(a[0], a[1], " ".join(map(str, a[2])))
|
|
1845
1850
|
for a in self.scripts
|
|
1846
1851
|
]
|
|
1852
|
+
minmaxes = [
|
|
1853
|
+
"\n{}Axis.MinMax {} {} {}, {};".format(direction, a[0], a[1], a[2], a[3])
|
|
1854
|
+
for a in self.minmax
|
|
1855
|
+
]
|
|
1847
1856
|
return "{}Axis.BaseTagList {};\n{}{}Axis.BaseScriptList {};".format(
|
|
1848
1857
|
direction, " ".join(self.bases), indent, direction, ", ".join(scripts)
|
|
1849
|
-
)
|
|
1858
|
+
) + "\n".join(minmaxes)
|
|
1850
1859
|
|
|
1851
1860
|
|
|
1852
1861
|
class OS2Field(Statement):
|
|
@@ -2098,7 +2107,7 @@ class VariationBlock(Block):
|
|
|
2098
2107
|
def build(self, builder):
|
|
2099
2108
|
"""Call the ``start_feature`` callback on the builder object, visit
|
|
2100
2109
|
all the statements in this feature, and then call ``end_feature``."""
|
|
2101
|
-
builder.start_feature(self.location, self.name)
|
|
2110
|
+
builder.start_feature(self.location, self.name, self.use_extension)
|
|
2102
2111
|
if (
|
|
2103
2112
|
self.conditionset != "NULL"
|
|
2104
2113
|
and self.conditionset not in builder.conditionsets_
|