Merge pull request #2784 from fonttools/varglyphset-cff
[ttVarGlyphSet] Support CFF
This commit is contained in:
commit
633bc2732f
@ -1125,8 +1125,9 @@ class CharStrings(object):
|
||||
"""
|
||||
|
||||
def __init__(self, file, charset, globalSubrs, private, fdSelect, fdArray,
|
||||
isCFF2=None):
|
||||
isCFF2=None, varStore=None):
|
||||
self.globalSubrs = globalSubrs
|
||||
self.varStore = varStore
|
||||
if file is not None:
|
||||
self.charStringsIndex = SubrsIndex(
|
||||
file, globalSubrs, private, fdSelect, fdArray, isCFF2=isCFF2)
|
||||
@ -1516,6 +1517,7 @@ class CharStringsConverter(TableConverter):
|
||||
file = parent.file
|
||||
isCFF2 = parent._isCFF2
|
||||
charset = parent.charset
|
||||
varStore = getattr(parent, "VarStore", None)
|
||||
globalSubrs = parent.GlobalSubrs
|
||||
if hasattr(parent, "FDArray"):
|
||||
fdArray = parent.FDArray
|
||||
@ -1529,7 +1531,7 @@ class CharStringsConverter(TableConverter):
|
||||
private = parent.Private
|
||||
file.seek(value) # Offset(0)
|
||||
charStrings = CharStrings(
|
||||
file, charset, globalSubrs, private, fdSelect, fdArray, isCFF2=isCFF2)
|
||||
file, charset, globalSubrs, private, fdSelect, fdArray, isCFF2=isCFF2, varStore=varStore)
|
||||
return charStrings
|
||||
|
||||
def write(self, parent, value):
|
||||
@ -1551,7 +1553,7 @@ class CharStringsConverter(TableConverter):
|
||||
# there is no fdArray.
|
||||
private, fdSelect, fdArray = parent.Private, None, None
|
||||
charStrings = CharStrings(
|
||||
None, None, parent.GlobalSubrs, private, fdSelect, fdArray)
|
||||
None, None, parent.GlobalSubrs, private, fdSelect, fdArray, varStore=getattr(parent, "VarStore", None))
|
||||
charStrings.fromXML(name, attrs, content)
|
||||
return charStrings
|
||||
|
||||
|
@ -263,12 +263,13 @@ class CharStringCompileError(Exception): pass
|
||||
|
||||
class SimpleT2Decompiler(object):
|
||||
|
||||
def __init__(self, localSubrs, globalSubrs, private=None):
|
||||
def __init__(self, localSubrs, globalSubrs, private=None, blender=None):
|
||||
self.localSubrs = localSubrs
|
||||
self.localBias = calcSubrBias(localSubrs)
|
||||
self.globalSubrs = globalSubrs
|
||||
self.globalBias = calcSubrBias(globalSubrs)
|
||||
self.private = private
|
||||
self.blender = blender
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
@ -277,6 +278,7 @@ class SimpleT2Decompiler(object):
|
||||
self.hintCount = 0
|
||||
self.hintMaskBytes = 0
|
||||
self.numRegions = 0
|
||||
self.vsIndex = 0
|
||||
|
||||
def execute(self, charString):
|
||||
self.callingStack.append(charString)
|
||||
@ -410,17 +412,28 @@ class SimpleT2Decompiler(object):
|
||||
def op_roll(self, index):
|
||||
raise NotImplementedError
|
||||
|
||||
# TODO(behdad): move to T2OutlineExtractor and add a 'setVariation'
|
||||
# method that takes VarStoreData and a location
|
||||
def op_blend(self, index):
|
||||
if self.numRegions == 0:
|
||||
self.numRegions = self.private.getNumRegions()
|
||||
numBlends = self.pop()
|
||||
numOps = numBlends * (self.numRegions + 1)
|
||||
if self.blender is None:
|
||||
del self.operandStack[-(numOps-numBlends):] # Leave the default operands on the stack.
|
||||
else:
|
||||
argi = len(self.operandStack) - numOps
|
||||
end_args = tuplei = argi + numBlends
|
||||
while argi < end_args:
|
||||
next_ti = tuplei + self.numRegions
|
||||
deltas = self.operandStack[tuplei:next_ti]
|
||||
delta = self.blender(self.vsIndex, deltas)
|
||||
self.operandStack[argi] += delta
|
||||
tuplei = next_ti
|
||||
argi += 1
|
||||
self.operandStack[end_args:] = []
|
||||
|
||||
def op_vsindex(self, index):
|
||||
vi = self.pop()
|
||||
self.vsIndex = vi
|
||||
self.numRegions = self.private.getNumRegions(vi)
|
||||
|
||||
|
||||
@ -456,8 +469,8 @@ t1Operators = [
|
||||
|
||||
class T2WidthExtractor(SimpleT2Decompiler):
|
||||
|
||||
def __init__(self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None):
|
||||
SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs, private)
|
||||
def __init__(self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None):
|
||||
SimpleT2Decompiler.__init__(self, localSubrs, globalSubrs, private, blender)
|
||||
self.nominalWidthX = nominalWidthX
|
||||
self.defaultWidthX = defaultWidthX
|
||||
|
||||
@ -498,9 +511,9 @@ class T2WidthExtractor(SimpleT2Decompiler):
|
||||
|
||||
class T2OutlineExtractor(T2WidthExtractor):
|
||||
|
||||
def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None):
|
||||
def __init__(self, pen, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private=None, blender=None):
|
||||
T2WidthExtractor.__init__(
|
||||
self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private)
|
||||
self, localSubrs, globalSubrs, nominalWidthX, defaultWidthX, private, blender)
|
||||
self.pen = pen
|
||||
self.subrLevel = 0
|
||||
|
||||
@ -986,11 +999,11 @@ class T2CharString(object):
|
||||
decompiler = self.decompilerClass(subrs, self.globalSubrs, self.private)
|
||||
decompiler.execute(self)
|
||||
|
||||
def draw(self, pen):
|
||||
def draw(self, pen, blender=None):
|
||||
subrs = getattr(self.private, "Subrs", [])
|
||||
extractor = self.outlineExtractor(pen, subrs, self.globalSubrs,
|
||||
self.private.nominalWidthX, self.private.defaultWidthX,
|
||||
self.private)
|
||||
self.private, blender)
|
||||
extractor.execute(self)
|
||||
self.width = extractor.width
|
||||
|
||||
|
@ -8,6 +8,7 @@ from fontTools.ttLib.ttGlyphSet import (
|
||||
_TTGlyphSet, _TTGlyph,
|
||||
_TTGlyphCFF, _TTGlyphGlyf,
|
||||
_TTVarGlyphSet,
|
||||
_TTVarGlyphCFF, _TTVarGlyphGlyf,
|
||||
)
|
||||
from fontTools.ttLib.sfnt import SFNTReader, SFNTWriter
|
||||
from io import BytesIO, StringIO
|
||||
@ -703,14 +704,17 @@ class TTFont(object):
|
||||
if (preferCFF and any(tb in self for tb in ["CFF ", "CFF2"]) or
|
||||
("glyf" not in self and any(tb in self for tb in ["CFF ", "CFF2"]))):
|
||||
table_tag = "CFF2" if "CFF2" in self else "CFF "
|
||||
if location:
|
||||
raise NotImplementedError # TODO
|
||||
glyphs = _TTGlyphSet(self,
|
||||
list(self[table_tag].cff.values())[0].CharStrings, _TTGlyphCFF)
|
||||
glyphs = list(self[table_tag].cff.values())[0].CharStrings
|
||||
if location and 'fvar' in self:
|
||||
glyphs = _TTVarGlyphSet(self, glyphs, _TTVarGlyphCFF,
|
||||
location, normalized)
|
||||
else:
|
||||
glyphs = _TTGlyphSet(self, glyphs, _TTGlyphCFF)
|
||||
|
||||
if glyphs is None and "glyf" in self:
|
||||
if location and 'gvar' in self:
|
||||
glyphs = _TTVarGlyphSet(self, location=location, normalized=normalized)
|
||||
glyphs = _TTVarGlyphSet(self, self["glyf"], _TTVarGlyphGlyf,
|
||||
location, normalized)
|
||||
else:
|
||||
glyphs = _TTGlyphSet(self, self["glyf"], _TTGlyphGlyf)
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
from fontTools.misc.fixedTools import otRound
|
||||
from copy import copy
|
||||
|
||||
|
||||
class _TTGlyphSet(object):
|
||||
|
||||
"""Generic dict-like GlyphSet class that pulls metrics from hmtx and
|
||||
@ -18,8 +19,8 @@ class _TTGlyphSet(object):
|
||||
glyphType (class): Either ``_TTGlyphCFF`` or ``_TTGlyphGlyf``.
|
||||
"""
|
||||
self._glyphs = glyphs
|
||||
self._hmtx = ttFont['hmtx']
|
||||
self._vmtx = ttFont['vmtx'] if 'vmtx' in ttFont else None
|
||||
self._hmtx = ttFont["hmtx"]
|
||||
self._vmtx = ttFont["vmtx"] if "vmtx" in ttFont else None
|
||||
self._glyphType = glyphType
|
||||
|
||||
def keys(self):
|
||||
@ -34,7 +35,8 @@ class _TTGlyphSet(object):
|
||||
horizontalMetrics = self._hmtx[glyphName]
|
||||
verticalMetrics = self._vmtx[glyphName] if self._vmtx else None
|
||||
return self._glyphType(
|
||||
self, self._glyphs[glyphName], horizontalMetrics, verticalMetrics)
|
||||
self, self._glyphs[glyphName], horizontalMetrics, verticalMetrics
|
||||
)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._glyphs)
|
||||
@ -45,6 +47,7 @@ class _TTGlyphSet(object):
|
||||
except KeyError:
|
||||
return default
|
||||
|
||||
|
||||
class _TTGlyph(object):
|
||||
|
||||
"""Wrapper for a TrueType glyph that supports the Pen protocol, meaning
|
||||
@ -56,7 +59,7 @@ class _TTGlyph(object):
|
||||
attributes.
|
||||
"""
|
||||
|
||||
def __init__(self, glyphset, glyph, horizontalMetrics, verticalMetrics=None):
|
||||
def __init__(self, glyphset, glyph, horizontalMetrics=None, verticalMetrics=None):
|
||||
"""Construct a new _TTGlyph.
|
||||
|
||||
Args:
|
||||
@ -66,7 +69,10 @@ class _TTGlyph(object):
|
||||
"""
|
||||
self._glyphset = glyphset
|
||||
self._glyph = glyph
|
||||
if horizontalMetrics:
|
||||
self.width, self.lsb = horizontalMetrics
|
||||
else:
|
||||
self.width, self.lsb = None, None
|
||||
if verticalMetrics:
|
||||
self.height, self.tsb = verticalMetrics
|
||||
else:
|
||||
@ -80,13 +86,15 @@ class _TTGlyph(object):
|
||||
|
||||
def drawPoints(self, pen):
|
||||
from fontTools.pens.pointPen import SegmentToPointPen
|
||||
|
||||
self.draw(SegmentToPointPen(pen))
|
||||
|
||||
|
||||
class _TTGlyphCFF(_TTGlyph):
|
||||
pass
|
||||
|
||||
class _TTGlyphGlyf(_TTGlyph):
|
||||
|
||||
class _TTGlyphGlyf(_TTGlyph):
|
||||
def draw(self, pen):
|
||||
"""Draw the glyph onto Pen. See fontTools.pens.basePen for details
|
||||
how that works.
|
||||
@ -106,20 +114,22 @@ class _TTGlyphGlyf(_TTGlyph):
|
||||
glyph.drawPoints(pen, glyfTable, offset)
|
||||
|
||||
|
||||
|
||||
class _TTVarGlyphSet(_TTGlyphSet):
|
||||
|
||||
def __init__(self, font, location, normalized=False):
|
||||
def __init__(self, font, glyphs, glyphType, location, normalized):
|
||||
self._ttFont = font
|
||||
self._glyphs = font['glyf']
|
||||
self._glyphs = glyphs
|
||||
self._glyphType = glyphType
|
||||
|
||||
if not normalized:
|
||||
from fontTools.varLib.models import normalizeLocation, piecewiseLinearMap
|
||||
|
||||
axes = {a.axisTag: (a.minValue, a.defaultValue, a.maxValue) for a in font['fvar'].axes}
|
||||
axes = {
|
||||
a.axisTag: (a.minValue, a.defaultValue, a.maxValue)
|
||||
for a in font["fvar"].axes
|
||||
}
|
||||
location = normalizeLocation(location, axes)
|
||||
if 'avar' in font:
|
||||
avar = font['avar']
|
||||
if "avar" in font:
|
||||
avar = font["avar"]
|
||||
avarSegments = avar.segments
|
||||
new_location = {}
|
||||
for axis_tag, value in location.items():
|
||||
@ -135,13 +145,13 @@ class _TTVarGlyphSet(_TTGlyphSet):
|
||||
def __getitem__(self, glyphName):
|
||||
if glyphName not in self._glyphs:
|
||||
raise KeyError(glyphName)
|
||||
return _TTVarGlyphGlyf(self._ttFont, glyphName, self.location)
|
||||
return self._glyphType(self, glyphName, self.location)
|
||||
|
||||
|
||||
def _setCoordinates(glyph, coord, glyfTable):
|
||||
# Handle phantom points for (left, right, top, bottom) positions.
|
||||
assert len(coord) >= 4
|
||||
if not hasattr(glyph, 'xMin'):
|
||||
if not hasattr(glyph, "xMin"):
|
||||
glyph.recalcBounds(glyfTable)
|
||||
leftSideX = coord[-4][0]
|
||||
rightSideX = coord[-3][0]
|
||||
@ -155,7 +165,7 @@ def _setCoordinates(glyph, coord, glyfTable):
|
||||
assert len(coord) == len(glyph.components)
|
||||
glyph.components = [copy(comp) for comp in glyph.components]
|
||||
for p, comp in zip(coord, glyph.components):
|
||||
if hasattr(comp, 'x'):
|
||||
if hasattr(comp, "x"):
|
||||
comp.x, comp.y = p
|
||||
elif glyph.numberOfContours == 0:
|
||||
assert len(coord) == 0
|
||||
@ -178,16 +188,47 @@ def _setCoordinates(glyph, coord, glyfTable):
|
||||
|
||||
|
||||
class _TTVarGlyph(_TTGlyph):
|
||||
def __init__(self, ttFont, glyphName, location):
|
||||
self._ttFont = ttFont
|
||||
def __init__(self, glyphSet, glyphName, location):
|
||||
|
||||
super().__init__(glyphSet._glyphs, glyphSet._glyphs[glyphName])
|
||||
|
||||
self._glyphSet = glyphSet
|
||||
self._ttFont = glyphSet._ttFont
|
||||
self._glyphs = glyphSet._glyphs
|
||||
self._glyphName = glyphName
|
||||
self._location = location
|
||||
# draw() fills these in
|
||||
self.width = self.height = self.lsb = self.tsb = None
|
||||
|
||||
|
||||
class _TTVarGlyphCFF(_TTVarGlyph):
|
||||
def draw(self, pen):
|
||||
varStore = self._glyphs.varStore
|
||||
if varStore is None:
|
||||
blender = None
|
||||
else:
|
||||
from fontTools.varLib.varStore import VarStoreInstancer
|
||||
|
||||
vsInstancer = getattr(self._glyphSet, "vsInstancer", None)
|
||||
if vsInstancer is None:
|
||||
self._glyphSet.vsInstancer = vsInstancer = VarStoreInstancer(
|
||||
varStore.otVarStore, self._ttFont["fvar"].axes, self._location
|
||||
)
|
||||
blender = vsInstancer.interpolateFromDeltas
|
||||
self._glyph.draw(pen, blender)
|
||||
|
||||
self.width = self._ttFont["hmtx"][self._glyphName][0]
|
||||
if "HVAR" in self._ttFont:
|
||||
hvar = self._ttFont["HVAR"].table
|
||||
varidx = self._ttFont.getGlyphID(self._glyphName)
|
||||
if hvar.AdvWidthMap is not None:
|
||||
varidx = hvar.AdvWidthMap.mapping[self._glyphName]
|
||||
vsInstancer = VarStoreInstancer(
|
||||
hvar.VarStore, self._ttFont["fvar"].axes, self._location
|
||||
)
|
||||
delta = vsInstancer[varidx]
|
||||
self.width += delta
|
||||
|
||||
|
||||
class _TTVarGlyphGlyf(_TTVarGlyph):
|
||||
|
||||
def draw(self, pen):
|
||||
self._drawWithPen(pen, isPointPen=False)
|
||||
|
||||
@ -199,12 +240,14 @@ class _TTVarGlyphGlyf(_TTVarGlyph):
|
||||
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
|
||||
from fontTools.varLib.models import supportScalar
|
||||
|
||||
glyf = self._ttFont['glyf']
|
||||
hMetrics = self._ttFont['hmtx'].metrics
|
||||
vMetrics = getattr(self._ttFont.get('vmtx'), 'metrics', None)
|
||||
glyf = self._ttFont["glyf"]
|
||||
hMetrics = self._ttFont["hmtx"].metrics
|
||||
vMetrics = getattr(self._ttFont.get("vmtx"), "metrics", None)
|
||||
|
||||
variations = self._ttFont['gvar'].variations[self._glyphName]
|
||||
coordinates, _ = glyf._getCoordinatesAndControls(self._glyphName, hMetrics, vMetrics)
|
||||
variations = self._ttFont["gvar"].variations[self._glyphName]
|
||||
coordinates, _ = glyf._getCoordinatesAndControls(
|
||||
self._glyphName, hMetrics, vMetrics
|
||||
)
|
||||
origCoords, endPts = None, None
|
||||
for var in variations:
|
||||
scalar = supportScalar(self._location, var.axes)
|
||||
@ -213,8 +256,12 @@ class _TTVarGlyphGlyf(_TTVarGlyph):
|
||||
delta = var.coordinates
|
||||
if None in delta:
|
||||
if origCoords is None:
|
||||
origCoords,control = glyf._getCoordinatesAndControls(self._glyphName, hMetrics, vMetrics)
|
||||
endPts = control[1] if control[0] >= 1 else list(range(len(control[1])))
|
||||
origCoords, control = glyf._getCoordinatesAndControls(
|
||||
self._glyphName, hMetrics, vMetrics
|
||||
)
|
||||
endPts = (
|
||||
control[1] if control[0] >= 1 else list(range(len(control[1])))
|
||||
)
|
||||
delta = iup_delta(delta, origCoords, endPts)
|
||||
coordinates += GlyphCoordinates(delta) * scalar
|
||||
|
||||
|
@ -448,9 +448,9 @@ class MergeOutlineExtractor(CFFToCFF2OutlineExtractor):
|
||||
into a CFF2 variable font charstring."""
|
||||
|
||||
def __init__(self, pen, localSubrs, globalSubrs,
|
||||
nominalWidthX, defaultWidthX, private=None):
|
||||
nominalWidthX, defaultWidthX, private=None, blender=None):
|
||||
super().__init__(pen, localSubrs,
|
||||
globalSubrs, nominalWidthX, defaultWidthX, private)
|
||||
globalSubrs, nominalWidthX, defaultWidthX, private, blender)
|
||||
|
||||
def countHints(self):
|
||||
args = self.popallWidth()
|
||||
|
BIN
Tests/ttLib/data/I.otf
Normal file
BIN
Tests/ttLib/data/I.otf
Normal file
Binary file not shown.
@ -6,82 +6,116 @@ import pytest
|
||||
|
||||
|
||||
class TTGlyphSetTest(object):
|
||||
|
||||
@staticmethod
|
||||
def getpath(testfile):
|
||||
path = os.path.dirname(__file__)
|
||||
return os.path.join(path, "data", testfile)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"location, expected",
|
||||
"fontfile, location, expected",
|
||||
[
|
||||
(
|
||||
"I.ttf",
|
||||
None,
|
||||
[
|
||||
('moveTo', ((175, 0),)),
|
||||
('lineTo', ((367, 0),)),
|
||||
('lineTo', ((367, 1456),)),
|
||||
('lineTo', ((175, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((175, 0),)),
|
||||
("lineTo", ((367, 0),)),
|
||||
("lineTo", ((367, 1456),)),
|
||||
("lineTo", ((175, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
(
|
||||
"I.ttf",
|
||||
{},
|
||||
[
|
||||
('moveTo', ((175, 0),)),
|
||||
('lineTo', ((367, 0),)),
|
||||
('lineTo', ((367, 1456),)),
|
||||
('lineTo', ((175, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((175, 0),)),
|
||||
("lineTo", ((367, 0),)),
|
||||
("lineTo", ((367, 1456),)),
|
||||
("lineTo", ((175, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
(
|
||||
{'wght': 100},
|
||||
"I.ttf",
|
||||
{"wght": 100},
|
||||
[
|
||||
('moveTo', ((175, 0),)),
|
||||
('lineTo', ((271, 0),)),
|
||||
('lineTo', ((271, 1456),)),
|
||||
('lineTo', ((175, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((175, 0),)),
|
||||
("lineTo", ((271, 0),)),
|
||||
("lineTo", ((271, 1456),)),
|
||||
("lineTo", ((175, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
(
|
||||
{'wght': 1000},
|
||||
"I.ttf",
|
||||
{"wght": 1000},
|
||||
[
|
||||
('moveTo', ((128, 0),)),
|
||||
('lineTo', ((550, 0),)),
|
||||
('lineTo', ((550, 1456),)),
|
||||
('lineTo', ((128, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((128, 0),)),
|
||||
("lineTo", ((550, 0),)),
|
||||
("lineTo", ((550, 1456),)),
|
||||
("lineTo", ((128, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
(
|
||||
{'wght': 1000, 'wdth': 25},
|
||||
"I.ttf",
|
||||
{"wght": 1000, "wdth": 25},
|
||||
[
|
||||
('moveTo', ((140, 0),)),
|
||||
('lineTo', ((553, 0),)),
|
||||
('lineTo', ((553, 1456),)),
|
||||
('lineTo', ((140, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((140, 0),)),
|
||||
("lineTo", ((553, 0),)),
|
||||
("lineTo", ((553, 1456),)),
|
||||
("lineTo", ((140, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
(
|
||||
{'wght': 1000, 'wdth': 50},
|
||||
"I.ttf",
|
||||
{"wght": 1000, "wdth": 50},
|
||||
[
|
||||
('moveTo', ((136, 0),)),
|
||||
('lineTo', ((552, 0),)),
|
||||
('lineTo', ((552, 1456),)),
|
||||
('lineTo', ((136, 1456),)),
|
||||
('closePath', ())
|
||||
]
|
||||
("moveTo", ((136, 0),)),
|
||||
("lineTo", ((552, 0),)),
|
||||
("lineTo", ((552, 1456),)),
|
||||
("lineTo", ((136, 1456),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
]
|
||||
(
|
||||
"I.otf",
|
||||
{"wght": 1000},
|
||||
[
|
||||
("moveTo", ((179, 74),)),
|
||||
("lineTo", ((28, 59),)),
|
||||
("lineTo", ((28, 0),)),
|
||||
("lineTo", ((367, 0),)),
|
||||
("lineTo", ((367, 59),)),
|
||||
("lineTo", ((212, 74),)),
|
||||
("lineTo", ((179, 74),)),
|
||||
("closePath", ()),
|
||||
("moveTo", ((179, 578),)),
|
||||
("lineTo", ((212, 578),)),
|
||||
("lineTo", ((367, 593),)),
|
||||
("lineTo", ((367, 652),)),
|
||||
("lineTo", ((28, 652),)),
|
||||
("lineTo", ((28, 593),)),
|
||||
("lineTo", ((179, 578),)),
|
||||
("closePath", ()),
|
||||
("moveTo", ((98, 310),)),
|
||||
("curveTo", ((98, 205), (98, 101), (95, 0))),
|
||||
("lineTo", ((299, 0),)),
|
||||
("curveTo", ((296, 103), (296, 207), (296, 311))),
|
||||
("lineTo", ((296, 342),)),
|
||||
("curveTo", ((296, 447), (296, 551), (299, 652))),
|
||||
("lineTo", ((95, 652),)),
|
||||
("curveTo", ((98, 549), (98, 445), (98, 342))),
|
||||
("lineTo", ((98, 310),)),
|
||||
("closePath", ()),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_glyphset(
|
||||
self, location, expected
|
||||
):
|
||||
# TODO: also test loading CFF-flavored fonts
|
||||
font = TTFont(self.getpath("I.ttf"))
|
||||
def test_glyphset(self, fontfile, location, expected):
|
||||
font = TTFont(self.getpath(fontfile))
|
||||
glyphset = font.getGlyphSet(location=location)
|
||||
|
||||
assert isinstance(glyphset, ttGlyphSet._TTGlyphSet)
|
||||
@ -96,17 +130,22 @@ class TTGlyphSetTest(object):
|
||||
assert len(glyphset) == 2
|
||||
|
||||
pen = RecordingPen()
|
||||
glyph = glyphset['I']
|
||||
glyph = glyphset["I"]
|
||||
|
||||
assert glyphset.get("foobar") is None
|
||||
|
||||
assert isinstance(glyph, ttGlyphSet._TTGlyph)
|
||||
is_glyf = fontfile.endswith(".ttf")
|
||||
if location:
|
||||
assert isinstance(glyph, ttGlyphSet._TTVarGlyphGlyf)
|
||||
glyphType = (
|
||||
ttGlyphSet._TTVarGlyphGlyf if is_glyf else ttGlyphSet._TTVarGlyphCFF
|
||||
)
|
||||
else:
|
||||
assert isinstance(glyph, ttGlyphSet._TTGlyphGlyf)
|
||||
glyphType = ttGlyphSet._TTGlyphGlyf if is_glyf else ttGlyphSet._TTGlyphCFF
|
||||
assert isinstance(glyph, glyphType)
|
||||
|
||||
glyph.draw(pen)
|
||||
actual = pen.value
|
||||
|
||||
print(actual)
|
||||
assert actual == expected, (location, actual, expected)
|
||||
|
Loading…
x
Reference in New Issue
Block a user