Merge branch 'fonttools:main' into ttf2otf
This commit is contained in:
commit
09df5fcc02
@ -46,7 +46,7 @@ class FreeTypePen(BasePen):
|
|||||||
glyphSet: a dictionary of drawable glyph objects keyed by name
|
glyphSet: a dictionary of drawable glyph objects keyed by name
|
||||||
used to resolve component references in composite glyphs.
|
used to resolve component references in composite glyphs.
|
||||||
|
|
||||||
:Examples:
|
Examples:
|
||||||
If `numpy` and `matplotlib` is available, the following code will
|
If `numpy` and `matplotlib` is available, the following code will
|
||||||
show the glyph image of `fi` in a new window::
|
show the glyph image of `fi` in a new window::
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ class FreeTypePen(BasePen):
|
|||||||
object of the resulted bitmap and ``size`` is a 2-tuple of its
|
object of the resulted bitmap and ``size`` is a 2-tuple of its
|
||||||
dimension.
|
dimension.
|
||||||
|
|
||||||
:Notes:
|
Notes:
|
||||||
The image size should always be given explicitly if you need to get
|
The image size should always be given explicitly if you need to get
|
||||||
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
||||||
forcifully fits to the bounding box and the side bearings get
|
forcifully fits to the bounding box and the side bearings get
|
||||||
@ -188,15 +188,15 @@ class FreeTypePen(BasePen):
|
|||||||
maintained but RSB won’t. The difference between the two becomes
|
maintained but RSB won’t. The difference between the two becomes
|
||||||
more obvious when rotate or skew transformation is applied.
|
more obvious when rotate or skew transformation is applied.
|
||||||
|
|
||||||
:Example:
|
Example:
|
||||||
.. code-block::
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>>
|
||||||
>> pen = FreeTypePen(None)
|
>> pen = FreeTypePen(None)
|
||||||
>> glyph.draw(pen)
|
>> glyph.draw(pen)
|
||||||
>> buf, size = pen.buffer(width=500, height=1000)
|
>> buf, size = pen.buffer(width=500, height=1000)
|
||||||
>> type(buf), len(buf), size
|
>> type(buf), len(buf), size
|
||||||
(<class 'bytes'>, 500000, (500, 1000))
|
(<class 'bytes'>, 500000, (500, 1000))
|
||||||
|
|
||||||
"""
|
"""
|
||||||
transform = transform or Transform()
|
transform = transform or Transform()
|
||||||
if not hasattr(transform, "transformPoint"):
|
if not hasattr(transform, "transformPoint"):
|
||||||
@ -269,7 +269,7 @@ class FreeTypePen(BasePen):
|
|||||||
A ``numpy.ndarray`` object with a shape of ``(height, width)``.
|
A ``numpy.ndarray`` object with a shape of ``(height, width)``.
|
||||||
Each element takes a value in the range of ``[0.0, 1.0]``.
|
Each element takes a value in the range of ``[0.0, 1.0]``.
|
||||||
|
|
||||||
:Notes:
|
Notes:
|
||||||
The image size should always be given explicitly if you need to get
|
The image size should always be given explicitly if you need to get
|
||||||
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
||||||
forcifully fits to the bounding box and the side bearings get
|
forcifully fits to the bounding box and the side bearings get
|
||||||
@ -279,15 +279,17 @@ class FreeTypePen(BasePen):
|
|||||||
maintained but RSB won’t. The difference between the two becomes
|
maintained but RSB won’t. The difference between the two becomes
|
||||||
more obvious when rotate or skew transformation is applied.
|
more obvious when rotate or skew transformation is applied.
|
||||||
|
|
||||||
:Example:
|
Example:
|
||||||
.. code-block::
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>>
|
||||||
>> pen = FreeTypePen(None)
|
>> pen = FreeTypePen(None)
|
||||||
>> glyph.draw(pen)
|
>> glyph.draw(pen)
|
||||||
>> arr = pen.array(width=500, height=1000)
|
>> arr = pen.array(width=500, height=1000)
|
||||||
>> type(a), a.shape
|
>> type(a), a.shape
|
||||||
(<class 'numpy.ndarray'>, (1000, 500))
|
(<class 'numpy.ndarray'>, (1000, 500))
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
buf, size = self.buffer(
|
buf, size = self.buffer(
|
||||||
@ -318,7 +320,7 @@ class FreeTypePen(BasePen):
|
|||||||
rendering glyphs with negative sidebearings without clipping.
|
rendering glyphs with negative sidebearings without clipping.
|
||||||
evenOdd: Pass ``True`` for even-odd fill instead of non-zero.
|
evenOdd: Pass ``True`` for even-odd fill instead of non-zero.
|
||||||
|
|
||||||
:Notes:
|
Notes:
|
||||||
The image size should always be given explicitly if you need to get
|
The image size should always be given explicitly if you need to get
|
||||||
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
||||||
forcifully fits to the bounding box and the side bearings get
|
forcifully fits to the bounding box and the side bearings get
|
||||||
@ -328,9 +330,10 @@ class FreeTypePen(BasePen):
|
|||||||
maintained but RSB won’t. The difference between the two becomes
|
maintained but RSB won’t. The difference between the two becomes
|
||||||
more obvious when rotate or skew transformation is applied.
|
more obvious when rotate or skew transformation is applied.
|
||||||
|
|
||||||
:Example:
|
Example:
|
||||||
.. code-block::
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>>
|
||||||
>> pen = FreeTypePen(None)
|
>> pen = FreeTypePen(None)
|
||||||
>> glyph.draw(pen)
|
>> glyph.draw(pen)
|
||||||
>> pen.show(width=500, height=1000)
|
>> pen.show(width=500, height=1000)
|
||||||
@ -370,7 +373,7 @@ class FreeTypePen(BasePen):
|
|||||||
A ``PIL.image`` object. The image is filled in black with alpha
|
A ``PIL.image`` object. The image is filled in black with alpha
|
||||||
channel obtained from the rendered bitmap.
|
channel obtained from the rendered bitmap.
|
||||||
|
|
||||||
:Notes:
|
Notes:
|
||||||
The image size should always be given explicitly if you need to get
|
The image size should always be given explicitly if you need to get
|
||||||
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
a proper glyph image. When ``width`` and ``height`` are omitted, it
|
||||||
forcifully fits to the bounding box and the side bearings get
|
forcifully fits to the bounding box and the side bearings get
|
||||||
@ -380,9 +383,10 @@ class FreeTypePen(BasePen):
|
|||||||
maintained but RSB won’t. The difference between the two becomes
|
maintained but RSB won’t. The difference between the two becomes
|
||||||
more obvious when rotate or skew transformation is applied.
|
more obvious when rotate or skew transformation is applied.
|
||||||
|
|
||||||
:Example:
|
Example:
|
||||||
.. code-block::
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>>
|
||||||
>> pen = FreeTypePen(None)
|
>> pen = FreeTypePen(None)
|
||||||
>> glyph.draw(pen)
|
>> glyph.draw(pen)
|
||||||
>> img = pen.image(width=500, height=1000)
|
>> img = pen.image(width=500, height=1000)
|
||||||
|
@ -15,7 +15,8 @@ class PointInsidePen(BasePen):
|
|||||||
Instances of this class can be recycled, as long as the
|
Instances of this class can be recycled, as long as the
|
||||||
setTestPoint() method is used to set the new point to test.
|
setTestPoint() method is used to set the new point to test.
|
||||||
|
|
||||||
Typical usage:
|
:Example:
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
pen = PointInsidePen(glyphSet, (100, 200))
|
pen = PointInsidePen(glyphSet, (100, 200))
|
||||||
outline.draw(pen)
|
outline.draw(pen)
|
||||||
|
@ -33,6 +33,7 @@ class RecordingPen(AbstractPen):
|
|||||||
pen.replay(otherPen).
|
pen.replay(otherPen).
|
||||||
|
|
||||||
:Example:
|
:Example:
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
from fontTools.ttLib import TTFont
|
from fontTools.ttLib import TTFont
|
||||||
from fontTools.pens.recordingPen import RecordingPen
|
from fontTools.pens.recordingPen import RecordingPen
|
||||||
@ -91,47 +92,48 @@ class DecomposingRecordingPen(DecomposingPen, RecordingPen):
|
|||||||
by thir name; other arguments are forwarded to the DecomposingPen's
|
by thir name; other arguments are forwarded to the DecomposingPen's
|
||||||
constructor::
|
constructor::
|
||||||
|
|
||||||
>>> class SimpleGlyph(object):
|
>>> class SimpleGlyph(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
... pen.moveTo((0, 0))
|
... pen.moveTo((0, 0))
|
||||||
... pen.curveTo((1, 1), (2, 2), (3, 3))
|
... pen.curveTo((1, 1), (2, 2), (3, 3))
|
||||||
... pen.closePath()
|
... pen.closePath()
|
||||||
>>> class CompositeGlyph(object):
|
>>> class CompositeGlyph(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
||||||
>>> class MissingComponent(object):
|
>>> class MissingComponent(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
||||||
>>> class FlippedComponent(object):
|
>>> class FlippedComponent(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
||||||
>>> glyphSet = {
|
>>> glyphSet = {
|
||||||
... 'a': SimpleGlyph(),
|
... 'a': SimpleGlyph(),
|
||||||
... 'b': CompositeGlyph(),
|
... 'b': CompositeGlyph(),
|
||||||
... 'c': MissingComponent(),
|
... 'c': MissingComponent(),
|
||||||
... 'd': FlippedComponent(),
|
... 'd': FlippedComponent(),
|
||||||
... }
|
... }
|
||||||
>>> for name, glyph in sorted(glyphSet.items()):
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
... pen = DecomposingRecordingPen(glyphSet)
|
... pen = DecomposingRecordingPen(glyphSet)
|
||||||
... try:
|
... try:
|
||||||
... glyph.draw(pen)
|
... glyph.draw(pen)
|
||||||
... except pen.MissingComponentError:
|
... except pen.MissingComponentError:
|
||||||
... pass
|
... pass
|
||||||
... print("{}: {}".format(name, pen.value))
|
... print("{}: {}".format(name, pen.value))
|
||||||
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
||||||
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
||||||
c: []
|
c: []
|
||||||
d: [('moveTo', ((0, 0),)), ('curveTo', ((-1, 1), (-2, 2), (-3, 3))), ('closePath', ())]
|
d: [('moveTo', ((0, 0),)), ('curveTo', ((-1, 1), (-2, 2), (-3, 3))), ('closePath', ())]
|
||||||
>>> for name, glyph in sorted(glyphSet.items()):
|
|
||||||
... pen = DecomposingRecordingPen(
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
... pen = DecomposingRecordingPen(
|
||||||
... )
|
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
||||||
... glyph.draw(pen)
|
... )
|
||||||
... print("{}: {}".format(name, pen.value))
|
... glyph.draw(pen)
|
||||||
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
... print("{}: {}".format(name, pen.value))
|
||||||
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
||||||
c: []
|
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
||||||
d: [('moveTo', ((0, 0),)), ('lineTo', ((-3, 3),)), ('curveTo', ((-2, 2), (-1, 1), (0, 0))), ('closePath', ())]
|
c: []
|
||||||
|
d: [('moveTo', ((0, 0),)), ('lineTo', ((-3, 3),)), ('curveTo', ((-2, 2), (-1, 1), (0, 0))), ('closePath', ())]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
||||||
@ -145,6 +147,7 @@ class RecordingPointPen(AbstractPointPen):
|
|||||||
pointPen.replay(otherPointPen).
|
pointPen.replay(otherPointPen).
|
||||||
|
|
||||||
:Example:
|
:Example:
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
from defcon import Font
|
from defcon import Font
|
||||||
from fontTools.pens.recordingPen import RecordingPointPen
|
from fontTools.pens.recordingPen import RecordingPointPen
|
||||||
@ -211,81 +214,82 @@ class DecomposingRecordingPointPen(DecomposingPointPen, RecordingPointPen):
|
|||||||
keyed by thir name; other arguments are forwarded to the DecomposingPointPen's
|
keyed by thir name; other arguments are forwarded to the DecomposingPointPen's
|
||||||
constructor::
|
constructor::
|
||||||
|
|
||||||
>>> from pprint import pprint
|
>>> from pprint import pprint
|
||||||
>>> class SimpleGlyph(object):
|
>>> class SimpleGlyph(object):
|
||||||
... def drawPoints(self, pen):
|
... def drawPoints(self, pen):
|
||||||
... pen.beginPath()
|
... pen.beginPath()
|
||||||
... pen.addPoint((0, 0), "line")
|
... pen.addPoint((0, 0), "line")
|
||||||
... pen.addPoint((1, 1))
|
... pen.addPoint((1, 1))
|
||||||
... pen.addPoint((2, 2))
|
... pen.addPoint((2, 2))
|
||||||
... pen.addPoint((3, 3), "curve")
|
... pen.addPoint((3, 3), "curve")
|
||||||
... pen.endPath()
|
... pen.endPath()
|
||||||
>>> class CompositeGlyph(object):
|
>>> class CompositeGlyph(object):
|
||||||
... def drawPoints(self, pen):
|
... def drawPoints(self, pen):
|
||||||
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
||||||
>>> class MissingComponent(object):
|
>>> class MissingComponent(object):
|
||||||
... def drawPoints(self, pen):
|
... def drawPoints(self, pen):
|
||||||
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
||||||
>>> class FlippedComponent(object):
|
>>> class FlippedComponent(object):
|
||||||
... def drawPoints(self, pen):
|
... def drawPoints(self, pen):
|
||||||
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
||||||
>>> glyphSet = {
|
>>> glyphSet = {
|
||||||
... 'a': SimpleGlyph(),
|
... 'a': SimpleGlyph(),
|
||||||
... 'b': CompositeGlyph(),
|
... 'b': CompositeGlyph(),
|
||||||
... 'c': MissingComponent(),
|
... 'c': MissingComponent(),
|
||||||
... 'd': FlippedComponent(),
|
... 'd': FlippedComponent(),
|
||||||
... }
|
... }
|
||||||
>>> for name, glyph in sorted(glyphSet.items()):
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
... pen = DecomposingRecordingPointPen(glyphSet)
|
... pen = DecomposingRecordingPointPen(glyphSet)
|
||||||
... try:
|
... try:
|
||||||
... glyph.drawPoints(pen)
|
... glyph.drawPoints(pen)
|
||||||
... except pen.MissingComponentError:
|
... except pen.MissingComponentError:
|
||||||
... pass
|
... pass
|
||||||
... pprint({name: pen.value})
|
... pprint({name: pen.value})
|
||||||
{'a': [('beginPath', (), {}),
|
{'a': [('beginPath', (), {}),
|
||||||
('addPoint', ((0, 0), 'line', False, None), {}),
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
('addPoint', ((1, 1), None, False, None), {}),
|
('addPoint', ((1, 1), None, False, None), {}),
|
||||||
('addPoint', ((2, 2), None, False, None), {}),
|
('addPoint', ((2, 2), None, False, None), {}),
|
||||||
('addPoint', ((3, 3), 'curve', False, None), {}),
|
('addPoint', ((3, 3), 'curve', False, None), {}),
|
||||||
('endPath', (), {})]}
|
('endPath', (), {})]}
|
||||||
{'b': [('beginPath', (), {}),
|
{'b': [('beginPath', (), {}),
|
||||||
('addPoint', ((-1, 1), 'line', False, None), {}),
|
('addPoint', ((-1, 1), 'line', False, None), {}),
|
||||||
('addPoint', ((0, 2), None, False, None), {}),
|
('addPoint', ((0, 2), None, False, None), {}),
|
||||||
('addPoint', ((1, 3), None, False, None), {}),
|
('addPoint', ((1, 3), None, False, None), {}),
|
||||||
('addPoint', ((2, 4), 'curve', False, None), {}),
|
('addPoint', ((2, 4), 'curve', False, None), {}),
|
||||||
('endPath', (), {})]}
|
('endPath', (), {})]}
|
||||||
{'c': []}
|
{'c': []}
|
||||||
{'d': [('beginPath', (), {}),
|
{'d': [('beginPath', (), {}),
|
||||||
('addPoint', ((0, 0), 'line', False, None), {}),
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
('addPoint', ((-1, 1), None, False, None), {}),
|
('addPoint', ((-1, 1), None, False, None), {}),
|
||||||
('addPoint', ((-2, 2), None, False, None), {}),
|
('addPoint', ((-2, 2), None, False, None), {}),
|
||||||
('addPoint', ((-3, 3), 'curve', False, None), {}),
|
('addPoint', ((-3, 3), 'curve', False, None), {}),
|
||||||
('endPath', (), {})]}
|
('endPath', (), {})]}
|
||||||
>>> for name, glyph in sorted(glyphSet.items()):
|
|
||||||
... pen = DecomposingRecordingPointPen(
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
... pen = DecomposingRecordingPointPen(
|
||||||
... )
|
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
||||||
... glyph.drawPoints(pen)
|
... )
|
||||||
... pprint({name: pen.value})
|
... glyph.drawPoints(pen)
|
||||||
{'a': [('beginPath', (), {}),
|
... pprint({name: pen.value})
|
||||||
('addPoint', ((0, 0), 'line', False, None), {}),
|
{'a': [('beginPath', (), {}),
|
||||||
('addPoint', ((1, 1), None, False, None), {}),
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
('addPoint', ((2, 2), None, False, None), {}),
|
('addPoint', ((1, 1), None, False, None), {}),
|
||||||
('addPoint', ((3, 3), 'curve', False, None), {}),
|
('addPoint', ((2, 2), None, False, None), {}),
|
||||||
('endPath', (), {})]}
|
('addPoint', ((3, 3), 'curve', False, None), {}),
|
||||||
{'b': [('beginPath', (), {}),
|
('endPath', (), {})]}
|
||||||
('addPoint', ((-1, 1), 'line', False, None), {}),
|
{'b': [('beginPath', (), {}),
|
||||||
('addPoint', ((0, 2), None, False, None), {}),
|
('addPoint', ((-1, 1), 'line', False, None), {}),
|
||||||
('addPoint', ((1, 3), None, False, None), {}),
|
('addPoint', ((0, 2), None, False, None), {}),
|
||||||
('addPoint', ((2, 4), 'curve', False, None), {}),
|
('addPoint', ((1, 3), None, False, None), {}),
|
||||||
('endPath', (), {})]}
|
('addPoint', ((2, 4), 'curve', False, None), {}),
|
||||||
{'c': []}
|
('endPath', (), {})]}
|
||||||
{'d': [('beginPath', (), {}),
|
{'c': []}
|
||||||
('addPoint', ((0, 0), 'curve', False, None), {}),
|
{'d': [('beginPath', (), {}),
|
||||||
('addPoint', ((-3, 3), 'line', False, None), {}),
|
('addPoint', ((0, 0), 'curve', False, None), {}),
|
||||||
('addPoint', ((-2, 2), None, False, None), {}),
|
('addPoint', ((-3, 3), 'line', False, None), {}),
|
||||||
('addPoint', ((-1, 1), None, False, None), {}),
|
('addPoint', ((-2, 2), None, False, None), {}),
|
||||||
('endPath', (), {})]}
|
('addPoint', ((-1, 1), None, False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
||||||
|
@ -9,27 +9,30 @@ def pointToString(pt, ntos=str):
|
|||||||
class SVGPathPen(BasePen):
|
class SVGPathPen(BasePen):
|
||||||
"""Pen to draw SVG path d commands.
|
"""Pen to draw SVG path d commands.
|
||||||
|
|
||||||
Example::
|
|
||||||
>>> pen = SVGPathPen(None)
|
|
||||||
>>> pen.moveTo((0, 0))
|
|
||||||
>>> pen.lineTo((1, 1))
|
|
||||||
>>> pen.curveTo((2, 2), (3, 3), (4, 4))
|
|
||||||
>>> pen.closePath()
|
|
||||||
>>> pen.getCommands()
|
|
||||||
'M0 0 1 1C2 2 3 3 4 4Z'
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
glyphSet: a dictionary of drawable glyph objects keyed by name
|
glyphSet: a dictionary of drawable glyph objects keyed by name
|
||||||
used to resolve component references in composite glyphs.
|
used to resolve component references in composite glyphs.
|
||||||
ntos: a callable that takes a number and returns a string, to
|
ntos: a callable that takes a number and returns a string, to
|
||||||
customize how numbers are formatted (default: str).
|
customize how numbers are formatted (default: str).
|
||||||
|
|
||||||
|
:Example:
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
>>> pen = SVGPathPen(None)
|
||||||
|
>>> pen.moveTo((0, 0))
|
||||||
|
>>> pen.lineTo((1, 1))
|
||||||
|
>>> pen.curveTo((2, 2), (3, 3), (4, 4))
|
||||||
|
>>> pen.closePath()
|
||||||
|
>>> pen.getCommands()
|
||||||
|
'M0 0 1 1C2 2 3 3 4 4Z'
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Fonts have a coordinate system where Y grows up, whereas in SVG,
|
Fonts have a coordinate system where Y grows up, whereas in SVG,
|
||||||
Y grows down. As such, rendering path data from this pen in
|
Y grows down. As such, rendering path data from this pen in
|
||||||
SVG typically results in upside-down glyphs. You can fix this
|
SVG typically results in upside-down glyphs. You can fix this
|
||||||
by wrapping the data from this pen in an SVG group element with
|
by wrapping the data from this pen in an SVG group element with
|
||||||
transform, or wrap this pen in a transform pen. For example:
|
transform, or wrap this pen in a transform pen. For example:
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
spen = svgPathPen.SVGPathPen(glyphset)
|
spen = svgPathPen.SVGPathPen(glyphset)
|
||||||
pen= TransformPen(spen , (1, 0, 0, -1, 0, 0))
|
pen= TransformPen(spen , (1, 0, 0, -1, 0, 0))
|
||||||
|
@ -58,22 +58,27 @@ class TransformPointPen(FilterPointPen):
|
|||||||
"""PointPen that transforms all coordinates using a Affine transformation,
|
"""PointPen that transforms all coordinates using a Affine transformation,
|
||||||
and passes them to another PointPen.
|
and passes them to another PointPen.
|
||||||
|
|
||||||
>>> from fontTools.pens.recordingPen import RecordingPointPen
|
For example::
|
||||||
>>> rec = RecordingPointPen()
|
|
||||||
>>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5))
|
>>> from fontTools.pens.recordingPen import RecordingPointPen
|
||||||
>>> v = iter(rec.value)
|
>>> rec = RecordingPointPen()
|
||||||
>>> pen.beginPath(identifier="contour-0")
|
>>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5))
|
||||||
>>> next(v)
|
>>> v = iter(rec.value)
|
||||||
('beginPath', (), {'identifier': 'contour-0'})
|
>>> pen.beginPath(identifier="contour-0")
|
||||||
>>> pen.addPoint((100, 100), "line")
|
>>> next(v)
|
||||||
>>> next(v)
|
('beginPath', (), {'identifier': 'contour-0'})
|
||||||
('addPoint', ((190, 205), 'line', False, None), {})
|
|
||||||
>>> pen.endPath()
|
>>> pen.addPoint((100, 100), "line")
|
||||||
>>> next(v)
|
>>> next(v)
|
||||||
('endPath', (), {})
|
('addPoint', ((190, 205), 'line', False, None), {})
|
||||||
>>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0")
|
|
||||||
>>> next(v)
|
>>> pen.endPath()
|
||||||
('addComponent', ('a', <Transform [2 0 0 2 -30 15]>), {'identifier': 'component-0'})
|
>>> next(v)
|
||||||
|
('endPath', (), {})
|
||||||
|
|
||||||
|
>>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0")
|
||||||
|
>>> next(v)
|
||||||
|
('addComponent', ('a', <Transform [2 0 0 2 -30 15]>), {'identifier': 'component-0'})
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, outPointPen, transformation):
|
def __init__(self, outPointPen, transformation):
|
||||||
|
@ -14,6 +14,8 @@ class SVGPath(object):
|
|||||||
|
|
||||||
For example, reading from an SVG file and drawing to a Defcon Glyph:
|
For example, reading from an SVG file and drawing to a Defcon Glyph:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
import defcon
|
import defcon
|
||||||
glyph = defcon.Glyph()
|
glyph = defcon.Glyph()
|
||||||
pen = glyph.getPen()
|
pen = glyph.getPen()
|
||||||
@ -23,6 +25,8 @@ class SVGPath(object):
|
|||||||
Or reading from a string containing SVG data, using the alternative
|
Or reading from a string containing SVG data, using the alternative
|
||||||
'fromstring' (a class method):
|
'fromstring' (a class method):
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
data = '<?xml version="1.0" ...'
|
data = '<?xml version="1.0" ...'
|
||||||
svg = SVGPath.fromstring(data)
|
svg = SVGPath.fromstring(data)
|
||||||
svg.draw(pen)
|
svg.draw(pen)
|
||||||
|
@ -103,6 +103,8 @@ def parse_path(pathdef, pen, current_pos=(0, 0), arc_class=EllipticalArc):
|
|||||||
If the pen has an "arcTo" method, it is called with the original values
|
If the pen has an "arcTo" method, it is called with the original values
|
||||||
of the elliptical arc curve commands:
|
of the elliptical arc curve commands:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
pen.arcTo(rx, ry, rotation, arc_large, arc_sweep, (x, y))
|
pen.arcTo(rx, ry, rotation, arc_large, arc_sweep, (x, y))
|
||||||
|
|
||||||
Otherwise, the arcs are approximated by series of cubic Bezier segments
|
Otherwise, the arcs are approximated by series of cubic Bezier segments
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""ttLib/sfnt.py -- low-level module to deal with the sfnt file format.
|
"""ttLib/sfnt.py -- low-level module to deal with the sfnt file format.
|
||||||
|
|
||||||
Defines two public classes:
|
Defines two public classes:
|
||||||
SFNTReader
|
|
||||||
SFNTWriter
|
- SFNTReader
|
||||||
|
- SFNTWriter
|
||||||
|
|
||||||
(Normally you don't have to use these classes explicitly; they are
|
(Normally you don't have to use these classes explicitly; they are
|
||||||
used automatically by ttLib.TTFont.)
|
used automatically by ttLib.TTFont.)
|
||||||
|
@ -26,37 +26,43 @@ class TTFont(object):
|
|||||||
accessing tables. Tables will be only decompiled when necessary, ie. when
|
accessing tables. Tables will be only decompiled when necessary, ie. when
|
||||||
they're actually accessed. This means that simple operations can be extremely fast.
|
they're actually accessed. This means that simple operations can be extremely fast.
|
||||||
|
|
||||||
Example usage::
|
Example usage:
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
>> from fontTools import ttLib
|
>>>
|
||||||
>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file
|
>> from fontTools import ttLib
|
||||||
>> tt['maxp'].numGlyphs
|
>> tt = ttLib.TTFont("afont.ttf") # Load an existing font file
|
||||||
242
|
>> tt['maxp'].numGlyphs
|
||||||
>> tt['OS/2'].achVendID
|
242
|
||||||
'B&H\000'
|
>> tt['OS/2'].achVendID
|
||||||
>> tt['head'].unitsPerEm
|
'B&H\000'
|
||||||
2048
|
>> tt['head'].unitsPerEm
|
||||||
|
2048
|
||||||
|
|
||||||
For details of the objects returned when accessing each table, see :ref:`tables`.
|
For details of the objects returned when accessing each table, see :ref:`tables`.
|
||||||
To add a table to the font, use the :py:func:`newTable` function::
|
To add a table to the font, use the :py:func:`newTable` function:
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
>> os2 = newTable("OS/2")
|
>>>
|
||||||
>> os2.version = 4
|
>> os2 = newTable("OS/2")
|
||||||
>> # set other attributes
|
>> os2.version = 4
|
||||||
>> font["OS/2"] = os2
|
>> # set other attributes
|
||||||
|
>> font["OS/2"] = os2
|
||||||
|
|
||||||
TrueType fonts can also be serialized to and from XML format (see also the
|
TrueType fonts can also be serialized to and from XML format (see also the
|
||||||
:ref:`ttx` binary)::
|
:ref:`ttx` binary):
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
>> tt.saveXML("afont.ttx")
|
>>
|
||||||
Dumping 'LTSH' table...
|
>> tt.saveXML("afont.ttx")
|
||||||
Dumping 'OS/2' table...
|
Dumping 'LTSH' table...
|
||||||
[...]
|
Dumping 'OS/2' table...
|
||||||
|
[...]
|
||||||
|
|
||||||
>> tt2 = ttLib.TTFont() # Create a new font object
|
>> tt2 = ttLib.TTFont() # Create a new font object
|
||||||
>> tt2.importXML("afont.ttx")
|
>> tt2.importXML("afont.ttx")
|
||||||
>> tt2['maxp'].numGlyphs
|
>> tt2['maxp'].numGlyphs
|
||||||
242
|
242
|
||||||
|
|
||||||
The TTFont object may be used as a context manager; this will cause the file
|
The TTFont object may be used as a context manager; this will cause the file
|
||||||
reader to be closed after the context ``with`` block is exited::
|
reader to be closed after the context ``with`` block is exited::
|
||||||
@ -981,14 +987,16 @@ def tagToIdentifier(tag):
|
|||||||
letters get an underscore after the letter. Trailing spaces are
|
letters get an underscore after the letter. Trailing spaces are
|
||||||
trimmed. Illegal characters are escaped as two hex bytes. If the
|
trimmed. Illegal characters are escaped as two hex bytes. If the
|
||||||
result starts with a number (as the result of a hex escape), an
|
result starts with a number (as the result of a hex escape), an
|
||||||
extra underscore is prepended. Examples::
|
extra underscore is prepended. Examples:
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
>>> tagToIdentifier('glyf')
|
>>>
|
||||||
'_g_l_y_f'
|
>> tagToIdentifier('glyf')
|
||||||
>>> tagToIdentifier('cvt ')
|
'_g_l_y_f'
|
||||||
'_c_v_t'
|
>> tagToIdentifier('cvt ')
|
||||||
>>> tagToIdentifier('OS/2')
|
'_c_v_t'
|
||||||
'O_S_2f_2'
|
>> tagToIdentifier('OS/2')
|
||||||
|
'O_S_2f_2'
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -7,25 +7,29 @@ of the specification.
|
|||||||
|
|
||||||
Sets that list the font info attribute names for the fontinfo.plist
|
Sets that list the font info attribute names for the fontinfo.plist
|
||||||
formats are available for external use. These are:
|
formats are available for external use. These are:
|
||||||
fontInfoAttributesVersion1
|
|
||||||
fontInfoAttributesVersion2
|
- fontInfoAttributesVersion1
|
||||||
fontInfoAttributesVersion3
|
- fontInfoAttributesVersion2
|
||||||
|
- fontInfoAttributesVersion3
|
||||||
|
|
||||||
A set listing the fontinfo.plist attributes that were deprecated
|
A set listing the fontinfo.plist attributes that were deprecated
|
||||||
in version 2 is available for external use:
|
in version 2 is available for external use:
|
||||||
deprecatedFontInfoAttributesVersion2
|
|
||||||
|
- deprecatedFontInfoAttributesVersion2
|
||||||
|
|
||||||
Functions that do basic validation on values for fontinfo.plist
|
Functions that do basic validation on values for fontinfo.plist
|
||||||
are available for external use. These are
|
are available for external use. These are
|
||||||
validateFontInfoVersion2ValueForAttribute
|
|
||||||
validateFontInfoVersion3ValueForAttribute
|
- validateFontInfoVersion2ValueForAttribute
|
||||||
|
- validateFontInfoVersion3ValueForAttribute
|
||||||
|
|
||||||
Value conversion functions are available for converting
|
Value conversion functions are available for converting
|
||||||
fontinfo.plist values between the possible format versions.
|
fontinfo.plist values between the possible format versions.
|
||||||
convertFontInfoValueForAttributeFromVersion1ToVersion2
|
|
||||||
convertFontInfoValueForAttributeFromVersion2ToVersion1
|
- convertFontInfoValueForAttributeFromVersion1ToVersion2
|
||||||
convertFontInfoValueForAttributeFromVersion2ToVersion3
|
- convertFontInfoValueForAttributeFromVersion2ToVersion1
|
||||||
convertFontInfoValueForAttributeFromVersion3ToVersion2
|
- convertFontInfoValueForAttributeFromVersion2ToVersion3
|
||||||
|
- convertFontInfoValueForAttributeFromVersion3ToVersion2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -10,10 +10,14 @@ ttf-interpolatable files for the masters and build a variable-font from
|
|||||||
them. Such ttf-interpolatable and designspace files can be generated from
|
them. Such ttf-interpolatable and designspace files can be generated from
|
||||||
a Glyphs source, eg., using noto-source as an example:
|
a Glyphs source, eg., using noto-source as an example:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
$ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs
|
$ fontmake -o ttf-interpolatable -g NotoSansArabic-MM.glyphs
|
||||||
|
|
||||||
Then you can make a variable-font this way:
|
Then you can make a variable-font this way:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
$ fonttools varLib master_ufo/NotoSansArabic.designspace
|
$ fonttools varLib master_ufo/NotoSansArabic.designspace
|
||||||
|
|
||||||
API *will* change in near future.
|
API *will* change in near future.
|
||||||
|
@ -96,7 +96,7 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
|
|||||||
|
|
||||||
* step through each key in FontDict.Private.
|
* step through each key in FontDict.Private.
|
||||||
* For each key, step through each relevant source font Private dict, and
|
* For each key, step through each relevant source font Private dict, and
|
||||||
build a list of values to blend.
|
build a list of values to blend.
|
||||||
|
|
||||||
The 'relevant' source fonts are selected by first getting the right
|
The 'relevant' source fonts are selected by first getting the right
|
||||||
submodel using ``vsindex_dict[vsindex]``. The indices of the
|
submodel using ``vsindex_dict[vsindex]``. The indices of the
|
||||||
|
@ -5,7 +5,9 @@ create full instances (i.e. static fonts) from variable fonts, as well as "parti
|
|||||||
variable fonts that only contain a subset of the original variation space.
|
variable fonts that only contain a subset of the original variation space.
|
||||||
|
|
||||||
For example, if you wish to pin the width axis to a given location while also
|
For example, if you wish to pin the width axis to a given location while also
|
||||||
restricting the weight axis to 400..700 range, you can do::
|
restricting the weight axis to 400..700 range, you can do:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
$ fonttools varLib.instancer ./NotoSans-VF.ttf wdth=85 wght=400:700
|
$ fonttools varLib.instancer ./NotoSans-VF.ttf wdth=85 wght=400:700
|
||||||
|
|
||||||
@ -17,32 +19,38 @@ and returns a new TTFont representing either a partial VF, or full instance if a
|
|||||||
the VF axes were given an explicit coordinate.
|
the VF axes were given an explicit coordinate.
|
||||||
|
|
||||||
E.g. here's how to pin the wght axis at a given location in a wght+wdth variable
|
E.g. here's how to pin the wght axis at a given location in a wght+wdth variable
|
||||||
font, keeping only the deltas associated with the wdth axis::
|
font, keeping only the deltas associated with the wdth axis:
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
| >>> from fontTools import ttLib
|
>>>
|
||||||
| >>> from fontTools.varLib import instancer
|
>> from fontTools import ttLib
|
||||||
| >>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf")
|
>> from fontTools.varLib import instancer
|
||||||
| >>> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes
|
>> varfont = ttLib.TTFont("path/to/MyVariableFont.ttf")
|
||||||
| ['wght', 'wdth']
|
>> [a.axisTag for a in varfont["fvar"].axes] # the varfont's current axes
|
||||||
| >>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300})
|
['wght', 'wdth']
|
||||||
| >>> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght'
|
>> partial = instancer.instantiateVariableFont(varfont, {"wght": 300})
|
||||||
| ['wdth']
|
>> [a.axisTag for a in partial["fvar"].axes] # axes left after pinning 'wght'
|
||||||
|
['wdth']
|
||||||
|
|
||||||
If the input location specifies all the axes, the resulting instance is no longer
|
If the input location specifies all the axes, the resulting instance is no longer
|
||||||
'variable' (same as using fontools varLib.mutator):
|
'variable' (same as using fontools varLib.mutator):
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
| >>> instance = instancer.instantiateVariableFont(
|
>>>
|
||||||
| ... varfont, {"wght": 700, "wdth": 67.5}
|
>> instance = instancer.instantiateVariableFont(
|
||||||
| ... )
|
... varfont, {"wght": 700, "wdth": 67.5}
|
||||||
| >>> "fvar" not in instance
|
... )
|
||||||
| True
|
>> "fvar" not in instance
|
||||||
|
True
|
||||||
|
|
||||||
If one just want to drop an axis at the default location, without knowing in
|
If one just want to drop an axis at the default location, without knowing in
|
||||||
advance what the default value for that axis is, one can pass a `None` value:
|
advance what the default value for that axis is, one can pass a `None` value:
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
| >>> instance = instancer.instantiateVariableFont(varfont, {"wght": None})
|
>>>
|
||||||
| >>> len(varfont["fvar"].axes)
|
>> instance = instancer.instantiateVariableFont(varfont, {"wght": None})
|
||||||
| 1
|
>> len(varfont["fvar"].axes)
|
||||||
|
1
|
||||||
|
|
||||||
From the console script, this is equivalent to passing `wght=drop` as input.
|
From the console script, this is equivalent to passing `wght=drop` as input.
|
||||||
|
|
||||||
@ -56,25 +64,33 @@ course be combined:
|
|||||||
|
|
||||||
L1
|
L1
|
||||||
dropping one or more axes while leaving the default tables unmodified;
|
dropping one or more axes while leaving the default tables unmodified;
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
| >>> font = instancer.instantiateVariableFont(varfont, {"wght": None})
|
>>>
|
||||||
|
>> font = instancer.instantiateVariableFont(varfont, {"wght": None})
|
||||||
|
|
||||||
L2
|
L2
|
||||||
dropping one or more axes while pinning them at non-default locations;
|
dropping one or more axes while pinning them at non-default locations;
|
||||||
|
.. code-block:: pycon
|
||||||
| >>> font = instancer.instantiateVariableFont(varfont, {"wght": 700})
|
|
||||||
|
>>>
|
||||||
|
>> font = instancer.instantiateVariableFont(varfont, {"wght": 700})
|
||||||
|
|
||||||
L3
|
L3
|
||||||
restricting the range of variation of one or more axes, by setting either
|
restricting the range of variation of one or more axes, by setting either
|
||||||
a new minimum or maximum, potentially -- though not necessarily -- dropping
|
a new minimum or maximum, potentially -- though not necessarily -- dropping
|
||||||
entire regions of variations that fall completely outside this new range.
|
entire regions of variations that fall completely outside this new range.
|
||||||
|
.. code-block:: pycon
|
||||||
| >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)})
|
|
||||||
|
>>>
|
||||||
|
>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300)})
|
||||||
|
|
||||||
L4
|
L4
|
||||||
moving the default location of an axis, by specifying (min,defalt,max) values:
|
moving the default location of an axis, by specifying (min,defalt,max) values:
|
||||||
|
.. code-block:: pycon
|
||||||
| >>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)})
|
|
||||||
|
>>>
|
||||||
|
>> font = instancer.instantiateVariableFont(varfont, {"wght": (100, 300, 700)})
|
||||||
|
|
||||||
Currently only TrueType-flavored variable fonts (i.e. containing 'glyf' table)
|
Currently only TrueType-flavored variable fonts (i.e. containing 'glyf' table)
|
||||||
are supported, but support for CFF2 variable fonts will be added soon.
|
are supported, but support for CFF2 variable fonts will be added soon.
|
||||||
@ -897,7 +913,18 @@ def _instantiateGvarGlyph(
|
|||||||
return
|
return
|
||||||
|
|
||||||
if optimize:
|
if optimize:
|
||||||
|
# IUP semantics depend on point equality, and so round prior to
|
||||||
|
# optimization to ensure that comparisons that happen now will be the
|
||||||
|
# same as those that happen at render time. This is especially needed
|
||||||
|
# when floating point deltas have been applied to the default position.
|
||||||
|
# See https://github.com/fonttools/fonttools/issues/3634
|
||||||
|
# Rounding must happen only after calculating glyf metrics above, to
|
||||||
|
# preserve backwards compatibility.
|
||||||
|
# See 0010a3cd9aa25f84a3a6250dafb119743d32aa40
|
||||||
|
coordinates.toInt()
|
||||||
|
|
||||||
isComposite = glyf[glyphname].isComposite()
|
isComposite = glyf[glyphname].isComposite()
|
||||||
|
|
||||||
for var in tupleVarStore:
|
for var in tupleVarStore:
|
||||||
var.optimize(coordinates, endPts, isComposite=isComposite)
|
var.optimize(coordinates, endPts, isComposite=isComposite)
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
Instantiate a variation font. Run, eg:
|
Instantiate a variation font. Run, eg:
|
||||||
|
|
||||||
$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
|
.. code-block:: sh
|
||||||
|
|
||||||
|
$ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed
|
from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed
|
||||||
@ -162,7 +164,9 @@ def instantiateVariableFont(varfont, location, inplace=False, overlap=True):
|
|||||||
defining the desired location along the variable font's axes.
|
defining the desired location along the variable font's axes.
|
||||||
The location values must be specified as user-space coordinates, e.g.:
|
The location values must be specified as user-space coordinates, e.g.:
|
||||||
|
|
||||||
{'wght': 400, 'wdth': 100}
|
.. code-block::
|
||||||
|
|
||||||
|
{'wght': 400, 'wdth': 100}
|
||||||
|
|
||||||
By default, a new TTFont object is returned. If ``inplace`` is True, the
|
By default, a new TTFont object is returned. If ``inplace`` is True, the
|
||||||
input varfont is modified and reduced to a static font.
|
input varfont is modified and reduced to a static font.
|
||||||
|
@ -7,12 +7,16 @@ Usage
|
|||||||
To convert a VTP project file:
|
To convert a VTP project file:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
$ fonttools voltLib.voltToFea input.vtp output.fea
|
$ fonttools voltLib.voltToFea input.vtp output.fea
|
||||||
|
|
||||||
It is also possible convert font files with `TSIV` table (as saved from Volt),
|
It is also possible convert font files with `TSIV` table (as saved from Volt),
|
||||||
in this case the glyph names used in the Volt project will be mapped to the
|
in this case the glyph names used in the Volt project will be mapped to the
|
||||||
actual glyph names in the font files when written to the feature file:
|
actual glyph names in the font files when written to the feature file:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
$ fonttools voltLib.voltToFea input.ttf output.fea
|
$ fonttools voltLib.voltToFea input.ttf output.fea
|
||||||
|
|
||||||
The ``--quiet`` option can be used to suppress warnings.
|
The ``--quiet`` option can be used to suppress warnings.
|
||||||
|
294
Tests/varLib/instancer/data/3634-VF.ttx
Normal file
294
Tests/varLib/instancer/data/3634-VF.ttx
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.53">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="A"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="1.0"/>
|
||||||
|
<fontRevision value="0.0"/>
|
||||||
|
<checkSumAdjustment value="0x139cb6b8"/>
|
||||||
|
<magicNumber value="0x5f0f3cf5"/>
|
||||||
|
<flags value="00000000 00000011"/>
|
||||||
|
<unitsPerEm value="1000"/>
|
||||||
|
<created value="Wed Sep 11 11:44:03 2024"/>
|
||||||
|
<modified value="Wed Sep 11 11:44:03 2024"/>
|
||||||
|
<xMin value="0"/>
|
||||||
|
<yMin value="-200"/>
|
||||||
|
<xMax value="1000"/>
|
||||||
|
<yMax value="1000"/>
|
||||||
|
<macStyle value="00000000 00000000"/>
|
||||||
|
<lowestRecPPEM value="6"/>
|
||||||
|
<fontDirectionHint value="2"/>
|
||||||
|
<indexToLocFormat value="0"/>
|
||||||
|
<glyphDataFormat value="0"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<hhea>
|
||||||
|
<tableVersion value="0x00010000"/>
|
||||||
|
<ascent value="1000"/>
|
||||||
|
<descent value="-200"/>
|
||||||
|
<lineGap value="0"/>
|
||||||
|
<advanceWidthMax value="1000"/>
|
||||||
|
<minLeftSideBearing value="0"/>
|
||||||
|
<minRightSideBearing value="0"/>
|
||||||
|
<xMaxExtent value="1000"/>
|
||||||
|
<caretSlopeRise value="1"/>
|
||||||
|
<caretSlopeRun value="0"/>
|
||||||
|
<caretOffset value="0"/>
|
||||||
|
<reserved0 value="0"/>
|
||||||
|
<reserved1 value="0"/>
|
||||||
|
<reserved2 value="0"/>
|
||||||
|
<reserved3 value="0"/>
|
||||||
|
<metricDataFormat value="0"/>
|
||||||
|
<numberOfHMetrics value="2"/>
|
||||||
|
</hhea>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="2"/>
|
||||||
|
<maxPoints value="8"/>
|
||||||
|
<maxContours value="2"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="1"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<OS_2>
|
||||||
|
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
|
||||||
|
will be recalculated by the compiler -->
|
||||||
|
<version value="4"/>
|
||||||
|
<xAvgCharWidth value="750"/>
|
||||||
|
<usWeightClass value="400"/>
|
||||||
|
<usWidthClass value="5"/>
|
||||||
|
<fsType value="00000000 00000100"/>
|
||||||
|
<ySubscriptXSize value="650"/>
|
||||||
|
<ySubscriptYSize value="600"/>
|
||||||
|
<ySubscriptXOffset value="0"/>
|
||||||
|
<ySubscriptYOffset value="75"/>
|
||||||
|
<ySuperscriptXSize value="650"/>
|
||||||
|
<ySuperscriptYSize value="600"/>
|
||||||
|
<ySuperscriptXOffset value="0"/>
|
||||||
|
<ySuperscriptYOffset value="350"/>
|
||||||
|
<yStrikeoutSize value="50"/>
|
||||||
|
<yStrikeoutPosition value="300"/>
|
||||||
|
<sFamilyClass value="0"/>
|
||||||
|
<panose>
|
||||||
|
<bFamilyType value="0"/>
|
||||||
|
<bSerifStyle value="0"/>
|
||||||
|
<bWeight value="0"/>
|
||||||
|
<bProportion value="0"/>
|
||||||
|
<bContrast value="0"/>
|
||||||
|
<bStrokeVariation value="0"/>
|
||||||
|
<bArmStyle value="0"/>
|
||||||
|
<bLetterForm value="0"/>
|
||||||
|
<bMidline value="0"/>
|
||||||
|
<bXHeight value="0"/>
|
||||||
|
</panose>
|
||||||
|
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
|
||||||
|
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<achVendID value="NONE"/>
|
||||||
|
<fsSelection value="00000000 01000000"/>
|
||||||
|
<usFirstCharIndex value="65"/>
|
||||||
|
<usLastCharIndex value="65"/>
|
||||||
|
<sTypoAscender value="800"/>
|
||||||
|
<sTypoDescender value="-200"/>
|
||||||
|
<sTypoLineGap value="200"/>
|
||||||
|
<usWinAscent value="1000"/>
|
||||||
|
<usWinDescent value="200"/>
|
||||||
|
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
|
||||||
|
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<sxHeight value="500"/>
|
||||||
|
<sCapHeight value="700"/>
|
||||||
|
<usDefaultChar value="0"/>
|
||||||
|
<usBreakChar value="32"/>
|
||||||
|
<usMaxContext value="0"/>
|
||||||
|
</OS_2>
|
||||||
|
|
||||||
|
<hmtx>
|
||||||
|
<mtx name=".notdef" width="500" lsb="50"/>
|
||||||
|
<mtx name="A" width="1000" lsb="0"/>
|
||||||
|
</hmtx>
|
||||||
|
|
||||||
|
<cmap>
|
||||||
|
<tableVersion version="0"/>
|
||||||
|
<cmap_format_4 platformID="0" platEncID="3" language="0">
|
||||||
|
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
|
||||||
|
</cmap_format_4>
|
||||||
|
<cmap_format_4 platformID="3" platEncID="1" language="0">
|
||||||
|
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
|
||||||
|
</cmap_format_4>
|
||||||
|
</cmap>
|
||||||
|
|
||||||
|
<loca>
|
||||||
|
<!-- The 'loca' table will be calculated by the compiler -->
|
||||||
|
</loca>
|
||||||
|
|
||||||
|
<glyf>
|
||||||
|
|
||||||
|
<!-- The xMin, yMin, xMax and yMax values
|
||||||
|
will be recalculated by the compiler. -->
|
||||||
|
|
||||||
|
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
|
||||||
|
<contour>
|
||||||
|
<pt x="50" y="-200" on="1"/>
|
||||||
|
<pt x="50" y="800" on="1"/>
|
||||||
|
<pt x="450" y="800" on="1"/>
|
||||||
|
<pt x="450" y="-200" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<contour>
|
||||||
|
<pt x="100" y="-150" on="1"/>
|
||||||
|
<pt x="400" y="-150" on="1"/>
|
||||||
|
<pt x="400" y="750" on="1"/>
|
||||||
|
<pt x="100" y="750" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<instructions/>
|
||||||
|
</TTGlyph>
|
||||||
|
|
||||||
|
<TTGlyph name="A" xMin="0" yMin="0" xMax="1000" yMax="1000">
|
||||||
|
<contour>
|
||||||
|
<pt x="0" y="1000" on="1"/>
|
||||||
|
<pt x="1000" y="1000" on="1"/>
|
||||||
|
<pt x="1000" y="0" on="1"/>
|
||||||
|
<pt x="0" y="0" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<instructions/>
|
||||||
|
</TTGlyph>
|
||||||
|
|
||||||
|
</glyf>
|
||||||
|
|
||||||
|
<name>
|
||||||
|
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
|
||||||
|
Weight
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
New Font
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
0.000;NONE;NewFont-Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
New Font Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Version 0.000
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
NewFont-Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Weight
|
||||||
|
</namerecord>
|
||||||
|
</name>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="-75"/>
|
||||||
|
<underlineThickness value="50"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<HVAR>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<VarStore Format="1">
|
||||||
|
<Format value="1"/>
|
||||||
|
<VarRegionList>
|
||||||
|
<!-- RegionAxisCount=1 -->
|
||||||
|
<!-- RegionCount=0 -->
|
||||||
|
</VarRegionList>
|
||||||
|
<!-- VarDataCount=1 -->
|
||||||
|
<VarData index="0">
|
||||||
|
<!-- ItemCount=1 -->
|
||||||
|
<NumShorts value="0"/>
|
||||||
|
<!-- VarRegionCount=0 -->
|
||||||
|
<Item index="0" value="[]"/>
|
||||||
|
</VarData>
|
||||||
|
</VarStore>
|
||||||
|
<AdvWidthMap>
|
||||||
|
<Map glyph=".notdef" outer="0" inner="0"/>
|
||||||
|
<Map glyph="A" outer="0" inner="0"/>
|
||||||
|
</AdvWidthMap>
|
||||||
|
</HVAR>
|
||||||
|
|
||||||
|
<STAT>
|
||||||
|
<Version value="0x00010001"/>
|
||||||
|
<DesignAxisRecordSize value="8"/>
|
||||||
|
<!-- DesignAxisCount=1 -->
|
||||||
|
<DesignAxisRecord>
|
||||||
|
<Axis index="0">
|
||||||
|
<AxisTag value="wght"/>
|
||||||
|
<AxisNameID value="256"/> <!-- Weight -->
|
||||||
|
<AxisOrdering value="0"/>
|
||||||
|
</Axis>
|
||||||
|
</DesignAxisRecord>
|
||||||
|
<!-- AxisValueCount=0 -->
|
||||||
|
<ElidedFallbackNameID value="2"/> <!-- Regular -->
|
||||||
|
</STAT>
|
||||||
|
|
||||||
|
<fvar>
|
||||||
|
|
||||||
|
<!-- Weight -->
|
||||||
|
<Axis>
|
||||||
|
<AxisTag>wght</AxisTag>
|
||||||
|
<Flags>0x0</Flags>
|
||||||
|
<MinValue>400.0</MinValue>
|
||||||
|
<DefaultValue>400.0</DefaultValue>
|
||||||
|
<MaxValue>900.0</MaxValue>
|
||||||
|
<AxisNameID>256</AxisNameID>
|
||||||
|
</Axis>
|
||||||
|
</fvar>
|
||||||
|
|
||||||
|
<gvar>
|
||||||
|
<version value="1"/>
|
||||||
|
<reserved value="0"/>
|
||||||
|
<glyphVariations glyph="A">
|
||||||
|
<tuple>
|
||||||
|
<coord axis="wght" value="1.0"/>
|
||||||
|
<delta pt="0" x="499" y="0"/>
|
||||||
|
<delta pt="1" x="500" y="0"/>
|
||||||
|
<delta pt="2" x="500" y="0"/>
|
||||||
|
<delta pt="3" x="500" y="0"/>
|
||||||
|
<delta pt="4" x="0" y="0"/>
|
||||||
|
<delta pt="5" x="0" y="0"/>
|
||||||
|
<delta pt="6" x="0" y="0"/>
|
||||||
|
<delta pt="7" x="0" y="0"/>
|
||||||
|
</tuple>
|
||||||
|
</glyphVariations>
|
||||||
|
</gvar>
|
||||||
|
|
||||||
|
</ttFont>
|
294
Tests/varLib/instancer/data/test_results/3634-VF-partial.ttx
Normal file
294
Tests/varLib/instancer/data/test_results/3634-VF-partial.ttx
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.53">
|
||||||
|
|
||||||
|
<GlyphOrder>
|
||||||
|
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
|
||||||
|
<GlyphID id="0" name=".notdef"/>
|
||||||
|
<GlyphID id="1" name="A"/>
|
||||||
|
</GlyphOrder>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="1.0"/>
|
||||||
|
<fontRevision value="0.0"/>
|
||||||
|
<checkSumAdjustment value="0xbd1ef780"/>
|
||||||
|
<magicNumber value="0x5f0f3cf5"/>
|
||||||
|
<flags value="00000000 00000011"/>
|
||||||
|
<unitsPerEm value="1000"/>
|
||||||
|
<created value="Wed Sep 11 11:44:03 2024"/>
|
||||||
|
<modified value="Wed Sep 11 12:08:44 2024"/>
|
||||||
|
<xMin value="1"/>
|
||||||
|
<yMin value="-200"/>
|
||||||
|
<xMax value="1001"/>
|
||||||
|
<yMax value="1000"/>
|
||||||
|
<macStyle value="00000000 00000000"/>
|
||||||
|
<lowestRecPPEM value="6"/>
|
||||||
|
<fontDirectionHint value="2"/>
|
||||||
|
<indexToLocFormat value="0"/>
|
||||||
|
<glyphDataFormat value="0"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<hhea>
|
||||||
|
<tableVersion value="0x00010000"/>
|
||||||
|
<ascent value="1000"/>
|
||||||
|
<descent value="-200"/>
|
||||||
|
<lineGap value="0"/>
|
||||||
|
<advanceWidthMax value="1000"/>
|
||||||
|
<minLeftSideBearing value="1"/>
|
||||||
|
<minRightSideBearing value="-1"/>
|
||||||
|
<xMaxExtent value="1001"/>
|
||||||
|
<caretSlopeRise value="1"/>
|
||||||
|
<caretSlopeRun value="0"/>
|
||||||
|
<caretOffset value="0"/>
|
||||||
|
<reserved0 value="0"/>
|
||||||
|
<reserved1 value="0"/>
|
||||||
|
<reserved2 value="0"/>
|
||||||
|
<reserved3 value="0"/>
|
||||||
|
<metricDataFormat value="0"/>
|
||||||
|
<numberOfHMetrics value="2"/>
|
||||||
|
</hhea>
|
||||||
|
|
||||||
|
<maxp>
|
||||||
|
<!-- Most of this table will be recalculated by the compiler -->
|
||||||
|
<tableVersion value="0x10000"/>
|
||||||
|
<numGlyphs value="2"/>
|
||||||
|
<maxPoints value="8"/>
|
||||||
|
<maxContours value="2"/>
|
||||||
|
<maxCompositePoints value="0"/>
|
||||||
|
<maxCompositeContours value="0"/>
|
||||||
|
<maxZones value="1"/>
|
||||||
|
<maxTwilightPoints value="0"/>
|
||||||
|
<maxStorage value="0"/>
|
||||||
|
<maxFunctionDefs value="0"/>
|
||||||
|
<maxInstructionDefs value="0"/>
|
||||||
|
<maxStackElements value="0"/>
|
||||||
|
<maxSizeOfInstructions value="0"/>
|
||||||
|
<maxComponentElements value="0"/>
|
||||||
|
<maxComponentDepth value="0"/>
|
||||||
|
</maxp>
|
||||||
|
|
||||||
|
<OS_2>
|
||||||
|
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
|
||||||
|
will be recalculated by the compiler -->
|
||||||
|
<version value="4"/>
|
||||||
|
<xAvgCharWidth value="750"/>
|
||||||
|
<usWeightClass value="401"/>
|
||||||
|
<usWidthClass value="5"/>
|
||||||
|
<fsType value="00000000 00000100"/>
|
||||||
|
<ySubscriptXSize value="650"/>
|
||||||
|
<ySubscriptYSize value="600"/>
|
||||||
|
<ySubscriptXOffset value="0"/>
|
||||||
|
<ySubscriptYOffset value="75"/>
|
||||||
|
<ySuperscriptXSize value="650"/>
|
||||||
|
<ySuperscriptYSize value="600"/>
|
||||||
|
<ySuperscriptXOffset value="0"/>
|
||||||
|
<ySuperscriptYOffset value="350"/>
|
||||||
|
<yStrikeoutSize value="50"/>
|
||||||
|
<yStrikeoutPosition value="300"/>
|
||||||
|
<sFamilyClass value="0"/>
|
||||||
|
<panose>
|
||||||
|
<bFamilyType value="0"/>
|
||||||
|
<bSerifStyle value="0"/>
|
||||||
|
<bWeight value="0"/>
|
||||||
|
<bProportion value="0"/>
|
||||||
|
<bContrast value="0"/>
|
||||||
|
<bStrokeVariation value="0"/>
|
||||||
|
<bArmStyle value="0"/>
|
||||||
|
<bLetterForm value="0"/>
|
||||||
|
<bMidline value="0"/>
|
||||||
|
<bXHeight value="0"/>
|
||||||
|
</panose>
|
||||||
|
<ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
|
||||||
|
<ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<achVendID value="NONE"/>
|
||||||
|
<fsSelection value="00000000 01000000"/>
|
||||||
|
<usFirstCharIndex value="65"/>
|
||||||
|
<usLastCharIndex value="65"/>
|
||||||
|
<sTypoAscender value="800"/>
|
||||||
|
<sTypoDescender value="-200"/>
|
||||||
|
<sTypoLineGap value="200"/>
|
||||||
|
<usWinAscent value="1000"/>
|
||||||
|
<usWinDescent value="200"/>
|
||||||
|
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
|
||||||
|
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
|
||||||
|
<sxHeight value="500"/>
|
||||||
|
<sCapHeight value="700"/>
|
||||||
|
<usDefaultChar value="0"/>
|
||||||
|
<usBreakChar value="32"/>
|
||||||
|
<usMaxContext value="0"/>
|
||||||
|
</OS_2>
|
||||||
|
|
||||||
|
<hmtx>
|
||||||
|
<mtx name=".notdef" width="500" lsb="50"/>
|
||||||
|
<mtx name="A" width="1000" lsb="1"/>
|
||||||
|
</hmtx>
|
||||||
|
|
||||||
|
<cmap>
|
||||||
|
<tableVersion version="0"/>
|
||||||
|
<cmap_format_4 platformID="0" platEncID="3" language="0">
|
||||||
|
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
|
||||||
|
</cmap_format_4>
|
||||||
|
<cmap_format_4 platformID="3" platEncID="1" language="0">
|
||||||
|
<map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
|
||||||
|
</cmap_format_4>
|
||||||
|
</cmap>
|
||||||
|
|
||||||
|
<loca>
|
||||||
|
<!-- The 'loca' table will be calculated by the compiler -->
|
||||||
|
</loca>
|
||||||
|
|
||||||
|
<glyf>
|
||||||
|
|
||||||
|
<!-- The xMin, yMin, xMax and yMax values
|
||||||
|
will be recalculated by the compiler. -->
|
||||||
|
|
||||||
|
<TTGlyph name=".notdef" xMin="50" yMin="-200" xMax="450" yMax="800">
|
||||||
|
<contour>
|
||||||
|
<pt x="50" y="-200" on="1"/>
|
||||||
|
<pt x="50" y="800" on="1"/>
|
||||||
|
<pt x="450" y="800" on="1"/>
|
||||||
|
<pt x="450" y="-200" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<contour>
|
||||||
|
<pt x="100" y="-150" on="1"/>
|
||||||
|
<pt x="400" y="-150" on="1"/>
|
||||||
|
<pt x="400" y="750" on="1"/>
|
||||||
|
<pt x="100" y="750" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<instructions/>
|
||||||
|
</TTGlyph>
|
||||||
|
|
||||||
|
<TTGlyph name="A" xMin="1" yMin="0" xMax="1001" yMax="1000">
|
||||||
|
<contour>
|
||||||
|
<pt x="1" y="1000" on="1"/>
|
||||||
|
<pt x="1001" y="1000" on="1"/>
|
||||||
|
<pt x="1001" y="0" on="1"/>
|
||||||
|
<pt x="1" y="0" on="1"/>
|
||||||
|
</contour>
|
||||||
|
<instructions/>
|
||||||
|
</TTGlyph>
|
||||||
|
|
||||||
|
</glyf>
|
||||||
|
|
||||||
|
<name>
|
||||||
|
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
|
||||||
|
Weight
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
New Font
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
0.000;NONE;NewFont-Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
New Font Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Version 0.000
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
NewFont-Regular
|
||||||
|
</namerecord>
|
||||||
|
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
|
||||||
|
Weight
|
||||||
|
</namerecord>
|
||||||
|
</name>
|
||||||
|
|
||||||
|
<post>
|
||||||
|
<formatType value="2.0"/>
|
||||||
|
<italicAngle value="0.0"/>
|
||||||
|
<underlinePosition value="-75"/>
|
||||||
|
<underlineThickness value="50"/>
|
||||||
|
<isFixedPitch value="0"/>
|
||||||
|
<minMemType42 value="0"/>
|
||||||
|
<maxMemType42 value="0"/>
|
||||||
|
<minMemType1 value="0"/>
|
||||||
|
<maxMemType1 value="0"/>
|
||||||
|
<psNames>
|
||||||
|
<!-- This file uses unique glyph names based on the information
|
||||||
|
found in the 'post' table. Since these names might not be unique,
|
||||||
|
we have to invent artificial names in case of clashes. In order to
|
||||||
|
be able to retain the original information, we need a name to
|
||||||
|
ps name mapping for those cases where they differ. That's what
|
||||||
|
you see below.
|
||||||
|
-->
|
||||||
|
</psNames>
|
||||||
|
<extraNames>
|
||||||
|
<!-- following are the name that are not taken from the standard Mac glyph order -->
|
||||||
|
</extraNames>
|
||||||
|
</post>
|
||||||
|
|
||||||
|
<HVAR>
|
||||||
|
<Version value="0x00010000"/>
|
||||||
|
<VarStore Format="1">
|
||||||
|
<Format value="1"/>
|
||||||
|
<VarRegionList>
|
||||||
|
<!-- RegionAxisCount=1 -->
|
||||||
|
<!-- RegionCount=0 -->
|
||||||
|
</VarRegionList>
|
||||||
|
<!-- VarDataCount=1 -->
|
||||||
|
<VarData index="0">
|
||||||
|
<!-- ItemCount=1 -->
|
||||||
|
<NumShorts value="0"/>
|
||||||
|
<!-- VarRegionCount=0 -->
|
||||||
|
<Item index="0" value="[]"/>
|
||||||
|
</VarData>
|
||||||
|
</VarStore>
|
||||||
|
<AdvWidthMap>
|
||||||
|
<Map glyph=".notdef" outer="0" inner="0"/>
|
||||||
|
<Map glyph="A" outer="0" inner="0"/>
|
||||||
|
</AdvWidthMap>
|
||||||
|
</HVAR>
|
||||||
|
|
||||||
|
<STAT>
|
||||||
|
<Version value="0x00010001"/>
|
||||||
|
<DesignAxisRecordSize value="8"/>
|
||||||
|
<!-- DesignAxisCount=1 -->
|
||||||
|
<DesignAxisRecord>
|
||||||
|
<Axis index="0">
|
||||||
|
<AxisTag value="wght"/>
|
||||||
|
<AxisNameID value="256"/> <!-- Weight -->
|
||||||
|
<AxisOrdering value="0"/>
|
||||||
|
</Axis>
|
||||||
|
</DesignAxisRecord>
|
||||||
|
<!-- AxisValueCount=0 -->
|
||||||
|
<ElidedFallbackNameID value="2"/> <!-- Regular -->
|
||||||
|
</STAT>
|
||||||
|
|
||||||
|
<fvar>
|
||||||
|
|
||||||
|
<!-- Weight -->
|
||||||
|
<Axis>
|
||||||
|
<AxisTag>wght</AxisTag>
|
||||||
|
<Flags>0x0</Flags>
|
||||||
|
<MinValue>401.0</MinValue>
|
||||||
|
<DefaultValue>401.0</DefaultValue>
|
||||||
|
<MaxValue>900.0</MaxValue>
|
||||||
|
<AxisNameID>256</AxisNameID>
|
||||||
|
</Axis>
|
||||||
|
</fvar>
|
||||||
|
|
||||||
|
<gvar>
|
||||||
|
<version value="1"/>
|
||||||
|
<reserved value="0"/>
|
||||||
|
<glyphVariations glyph="A">
|
||||||
|
<tuple>
|
||||||
|
<coord axis="wght" value="1.0"/>
|
||||||
|
<delta pt="0" x="498" y="0"/>
|
||||||
|
<delta pt="1" x="499" y="0"/>
|
||||||
|
<delta pt="2" x="499" y="0"/>
|
||||||
|
<delta pt="3" x="499" y="0"/>
|
||||||
|
<delta pt="4" x="0" y="0"/>
|
||||||
|
<delta pt="5" x="0" y="0"/>
|
||||||
|
<delta pt="6" x="0" y="0"/>
|
||||||
|
<delta pt="7" x="0" y="0"/>
|
||||||
|
</tuple>
|
||||||
|
</glyphVariations>
|
||||||
|
</gvar>
|
||||||
|
|
||||||
|
</ttFont>
|
@ -2390,3 +2390,41 @@ def test_set_ribbi_bits():
|
|||||||
assert name_id_2 == "Italic", location
|
assert name_id_2 == "Italic", location
|
||||||
assert mac_style == 0b10, location
|
assert mac_style == 0b10, location
|
||||||
assert fs_selection == 0b0000001, location
|
assert fs_selection == 0b0000001, location
|
||||||
|
|
||||||
|
|
||||||
|
def test_rounds_before_iup():
|
||||||
|
"""Regression test for fonttools/fonttools#3634, with TTX based on
|
||||||
|
reproduction process there."""
|
||||||
|
|
||||||
|
varfont = ttLib.TTFont()
|
||||||
|
varfont.importXML(os.path.join(TESTDATA, "3634-VF.ttx"))
|
||||||
|
|
||||||
|
# Instantiate at a new default position, sufficient to cause differences
|
||||||
|
# when unrounded but not when rounded.
|
||||||
|
partial = instancer.instantiateVariableFont(varfont, {"wght": (401, 401, 900)})
|
||||||
|
|
||||||
|
# Save and reload actual result to recalculate bounding box values, etc.
|
||||||
|
bytes_out = BytesIO()
|
||||||
|
partial.save(bytes_out)
|
||||||
|
bytes_out.seek(0)
|
||||||
|
partial = ttLib.TTFont(bytes_out)
|
||||||
|
|
||||||
|
# Load expected result, then save and reload to normalise TTX output.
|
||||||
|
expected = ttLib.TTFont()
|
||||||
|
expected.importXML(os.path.join(TESTDATA, "test_results", "3634-VF-partial.ttx"))
|
||||||
|
|
||||||
|
bytes_out = BytesIO()
|
||||||
|
expected.save(bytes_out)
|
||||||
|
bytes_out.seek(0)
|
||||||
|
expected = ttLib.TTFont(bytes_out)
|
||||||
|
|
||||||
|
# Serialise actual and expected to TTX strings, and compare.
|
||||||
|
string_out = StringIO()
|
||||||
|
partial.saveXML(string_out)
|
||||||
|
partial_ttx = stripVariableItemsFromTTX(string_out.getvalue())
|
||||||
|
|
||||||
|
string_out = StringIO()
|
||||||
|
expected.saveXML(string_out)
|
||||||
|
expected_ttx = stripVariableItemsFromTTX(string_out.getvalue())
|
||||||
|
|
||||||
|
assert partial_ttx == expected_ttx
|
||||||
|
Loading…
x
Reference in New Issue
Block a user