Merge pull request #3506 from fonttools/cff2-instancing

[instancer] CFF2 instancing
This commit is contained in:
Behdad Esfahbod 2024-05-17 13:17:12 -07:00 committed by GitHub
commit 65cc8bfb3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 4061 additions and 195 deletions

View File

@ -0,0 +1,165 @@
"""CFF2 to CFF converter."""
from fontTools.ttLib import TTFont, newTable
from fontTools.misc.cliTools import makeOutputFileName
from fontTools.cffLib import TopDictIndex, buildOrder, topDictOperators
from .width import optimizeWidths
from collections import defaultdict
import logging
__all__ = ["convertCFF2ToCFF", "main"]
log = logging.getLogger("fontTools.cffLib")
def _convertCFF2ToCFF(cff, otFont):
"""Converts this object from CFF2 format to CFF format. This conversion
is done 'in-place'. The conversion cannot be reversed.
The CFF2 font cannot be variable. (TODO Accept those and convert to the
default instance?)
This assumes a decompiled CFF table. (i.e. that the object has been
filled via :meth:`decompile` and e.g. not loaded from XML.)"""
cff.major = 1
topDictData = TopDictIndex(None, isCFF2=True)
for item in cff.topDictIndex:
# Iterate over, such that all are decompiled
topDictData.append(item)
cff.topDictIndex = topDictData
topDict = topDictData[0]
if hasattr(topDict, "VarStore"):
raise ValueError("Variable CFF2 font cannot be converted to CFF format.")
if hasattr(topDict, "Private"):
privateDict = topDict.Private
else:
privateDict = None
opOrder = buildOrder(topDictOperators)
topDict.order = opOrder
fdArray = topDict.FDArray
charStrings = topDict.CharStrings
for cs in charStrings.values():
cs.decompile()
cs.program.append("endchar")
for subrSets in [cff.GlobalSubrs] + [
getattr(fd.Private, "Subrs", []) for fd in fdArray
]:
for cs in subrSets:
cs.program.append("return")
# Add (optimal) width to CharStrings that need it.
widths = defaultdict(list)
metrics = otFont["hmtx"].metrics
for glyphName in charStrings.keys():
cs, fdIndex = charStrings.getItemAndSelector(glyphName)
if fdIndex == None:
fdIndex = 0
widths[fdIndex].append(metrics[glyphName][0])
for fdIndex, widthList in widths.items():
bestDefault, bestNominal = optimizeWidths(widthList)
private = fdArray[fdIndex].Private
private.defaultWidthX = bestDefault
private.nominalWidthX = bestNominal
for glyphName in charStrings.keys():
cs, fdIndex = charStrings.getItemAndSelector(glyphName)
if fdIndex == None:
fdIndex = 0
private = fdArray[fdIndex].Private
width = metrics[glyphName][0]
if width != private.defaultWidthX:
cs.program.insert(0, width - private.nominalWidthX)
def convertCFF2ToCFF(font, *, updatePostTable=True):
cff = font["CFF2"].cff
_convertCFF2ToCFF(cff, font)
del font["CFF2"]
table = font["CFF "] = newTable("CFF ")
table.cff = cff
if updatePostTable and "post" in font:
# Only version supported for fonts with CFF table is 0x00030000 not 0x20000
post = font["post"]
if post.formatType == 2.0:
post.formatType = 3.0
def main(args=None):
"""Convert CFF OTF font to CFF2 OTF font"""
if args is None:
import sys
args = sys.argv[1:]
import argparse
parser = argparse.ArgumentParser(
"fonttools cffLib.CFFToCFF2",
description="Upgrade a CFF font to CFF2.",
)
parser.add_argument(
"input", metavar="INPUT.ttf", help="Input OTF file with CFF table."
)
parser.add_argument(
"-o",
"--output",
metavar="OUTPUT.ttf",
default=None,
help="Output instance OTF file (default: INPUT-CFF2.ttf).",
)
parser.add_argument(
"--no-recalc-timestamp",
dest="recalc_timestamp",
action="store_false",
help="Don't set the output font's timestamp to the current time.",
)
loggingGroup = parser.add_mutually_exclusive_group(required=False)
loggingGroup.add_argument(
"-v", "--verbose", action="store_true", help="Run more verbosely."
)
loggingGroup.add_argument(
"-q", "--quiet", action="store_true", help="Turn verbosity off."
)
options = parser.parse_args(args)
from fontTools import configLogger
configLogger(
level=("DEBUG" if options.verbose else "ERROR" if options.quiet else "INFO")
)
import os
infile = options.input
if not os.path.isfile(infile):
parser.error("No such file '{}'".format(infile))
outfile = (
makeOutputFileName(infile, overWrite=True, suffix="-CFF")
if not options.output
else options.output
)
font = TTFont(infile, recalcTimestamp=options.recalc_timestamp, recalcBBoxes=False)
convertCFF2ToCFF(font)
log.info(
"Saving %s",
outfile,
)
font.save(outfile)
if __name__ == "__main__":
import sys
sys.exit(main(sys.argv[1:]))

View File

@ -0,0 +1,273 @@
"""CFF to CFF2 converter."""
from fontTools.ttLib import TTFont, newTable
from fontTools.misc.cliTools import makeOutputFileName
from fontTools.misc.psCharStrings import T2WidthExtractor
from fontTools.cffLib import (
TopDictIndex,
FDArrayIndex,
FontDict,
buildOrder,
topDictOperators,
privateDictOperators,
topDictOperators2,
privateDictOperators2,
)
from io import BytesIO
import logging
__all__ = ["convertCFFToCFF2", "main"]
log = logging.getLogger("fontTools.cffLib")
class _NominalWidthUsedError(Exception):
def __add__(self, other):
raise self
def __radd__(self, other):
raise self
def _convertCFFToCFF2(cff, otFont):
"""Converts this object from CFF format to CFF2 format. This conversion
is done 'in-place'. The conversion cannot be reversed.
This assumes a decompiled CFF table. (i.e. that the object has been
filled via :meth:`decompile` and e.g. not loaded from XML.)"""
# Clean up T2CharStrings
topDict = cff.topDictIndex[0]
fdArray = topDict.FDArray if hasattr(topDict, "FDArray") else None
charStrings = topDict.CharStrings
globalSubrs = cff.GlobalSubrs
localSubrs = [getattr(fd.Private, "Subrs", []) for fd in fdArray] if fdArray else []
for glyphName in charStrings.keys():
cs, fdIndex = charStrings.getItemAndSelector(glyphName)
cs.decompile()
# Clean up subroutines first
for subrs in [globalSubrs] + localSubrs:
for subr in subrs:
program = subr.program
i = j = len(program)
try:
i = program.index("return")
except ValueError:
pass
try:
j = program.index("endchar")
except ValueError:
pass
program[min(i, j) :] = []
# Clean up glyph charstrings
nominalWidthXError = _NominalWidthUsedError()
for glyphName in charStrings.keys():
cs, fdIndex = charStrings.getItemAndSelector(glyphName)
program = cs.program
if fdIndex == None:
fdIndex = 0
# Intentionally use custom type for nominalWidthX, such that any
# CharString that has an explicit width encoded will throw back to us.
extractor = T2WidthExtractor(
localSubrs[fdIndex] if localSubrs else [],
globalSubrs,
nominalWidthXError,
0,
)
try:
extractor.execute(cs)
except _NominalWidthUsedError:
# Program has explicit width. We want to drop it, but can't
# just pop the first number since it may be a subroutine call.
# Instead, when seeing that, we embed the subroutine and recurse.
# This has the problem that some subroutines might become unused.
# We don't currently prune those. Subset module has code for this
# kind of stuff, possibly plug it in here if pruning becomes needed.
while program[1] in ["callsubr", "callgsubr"]:
subrNumber = program.pop(0)
op = program.pop(0)
bias = extractor.localBias if op == "callsubr" else extractor.globalBias
subrNumber += bias
subrSet = localSubrs[fdIndex] if op == "callsubr" else globalSubrs
subrProgram = subrSet[subrNumber].program
program[:0] = subrProgram
# Now pop the actual width
program.pop(0)
if program and program[-1] == "endchar":
program.pop()
# Upconvert TopDict
cff.major = 2
cff2GetGlyphOrder = cff.otFont.getGlyphOrder
topDictData = TopDictIndex(None, cff2GetGlyphOrder)
for item in cff.topDictIndex:
# Iterate over, such that all are decompiled
topDictData.append(item)
cff.topDictIndex = topDictData
topDict = topDictData[0]
if hasattr(topDict, "Private"):
privateDict = topDict.Private
else:
privateDict = None
opOrder = buildOrder(topDictOperators2)
topDict.order = opOrder
topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
if not hasattr(topDict, "FDArray"):
fdArray = topDict.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = topDict.GlobalSubrs
topDict.GlobalSubrs.fdArray = fdArray
charStrings = topDict.CharStrings
if charStrings.charStringsAreIndexed:
charStrings.charStringsIndex.fdArray = fdArray
else:
charStrings.fdArray = fdArray
fontDict = FontDict()
fontDict.setCFF2(True)
fdArray.append(fontDict)
fontDict.Private = privateDict
privateOpOrder = buildOrder(privateDictOperators2)
if privateDict is not None:
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
else:
# clean up the PrivateDicts in the fdArray
fdArray = topDict.FDArray
privateOpOrder = buildOrder(privateDictOperators2)
for fontDict in fdArray:
fontDict.setCFF2(True)
for key in list(fontDict.rawDict.keys()):
if key not in fontDict.order:
del fontDict.rawDict[key]
if hasattr(fontDict, key):
delattr(fontDict, key)
privateDict = fontDict.Private
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in list(privateDict.rawDict.keys()):
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
# Now delete up the deprecated topDict operators from CFF 1.0
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
# TODO(behdad): What does the following comment even mean? Both CFF and CFF2
# use the same T2Charstring class. I *think* what it means is that the CharStrings
# were loaded for CFF1, and we need to reload them for CFF2 to set varstore, etc
# on them. At least that's what I understand. It's probably safe to remove this
# and just set vstore where needed.
# At this point, the Subrs and Charstrings are all still T2Charstring class
# easiest to fix this by compiling, then decompiling again
file = BytesIO()
cff.compile(file, otFont, isCFF2=True)
file.seek(0)
cff.decompile(file, otFont, isCFF2=True)
def convertCFFToCFF2(font):
cff = font["CFF "].cff
del font["CFF "]
_convertCFFToCFF2(cff, font)
table = font["CFF2"] = newTable("CFF2")
table.cff = cff
def main(args=None):
"""Convert CFF OTF font to CFF2 OTF font"""
if args is None:
import sys
args = sys.argv[1:]
import argparse
parser = argparse.ArgumentParser(
"fonttools cffLib.CFFToCFF2",
description="Upgrade a CFF font to CFF2.",
)
parser.add_argument(
"input", metavar="INPUT.ttf", help="Input OTF file with CFF table."
)
parser.add_argument(
"-o",
"--output",
metavar="OUTPUT.ttf",
default=None,
help="Output instance OTF file (default: INPUT-CFF2.ttf).",
)
parser.add_argument(
"--no-recalc-timestamp",
dest="recalc_timestamp",
action="store_false",
help="Don't set the output font's timestamp to the current time.",
)
loggingGroup = parser.add_mutually_exclusive_group(required=False)
loggingGroup.add_argument(
"-v", "--verbose", action="store_true", help="Run more verbosely."
)
loggingGroup.add_argument(
"-q", "--quiet", action="store_true", help="Turn verbosity off."
)
options = parser.parse_args(args)
from fontTools import configLogger
configLogger(
level=("DEBUG" if options.verbose else "ERROR" if options.quiet else "INFO")
)
import os
infile = options.input
if not os.path.isfile(infile):
parser.error("No such file '{}'".format(infile))
outfile = (
makeOutputFileName(infile, overWrite=True, suffix="-CFF2")
if not options.output
else options.output
)
font = TTFont(infile, recalcTimestamp=options.recalc_timestamp, recalcBBoxes=False)
convertCFFToCFF2(font)
log.info(
"Saving %s",
outfile,
)
font.save(outfile)
if __name__ == "__main__":
import sys
sys.exit(main(sys.argv[1:]))

View File

@ -99,9 +99,6 @@ class _DesubroutinizingT2Decompiler(psCharStrings.SimpleT2Decompiler):
desubroutinized = desubroutinized[ desubroutinized = desubroutinized[
: desubroutinized.index("endchar") + 1 : desubroutinized.index("endchar") + 1
] ]
else:
if not len(desubroutinized) or desubroutinized[-1] != "return":
desubroutinized.append("return")
charString._desubroutinized = desubroutinized charString._desubroutinized = desubroutinized
del charString._patches del charString._patches
@ -389,91 +386,20 @@ class CFFFontSet(object):
self.minor = int(attrs["value"]) self.minor = int(attrs["value"])
def convertCFFToCFF2(self, otFont): def convertCFFToCFF2(self, otFont):
"""Converts this object from CFF format to CFF2 format. This conversion from .CFFToCFF2 import _convertCFFToCFF2
is done 'in-place'. The conversion cannot be reversed.
This assumes a decompiled CFF table. (i.e. that the object has been _convertCFFToCFF2(self, otFont)
filled via :meth:`decompile`.)"""
self.major = 2
cff2GetGlyphOrder = self.otFont.getGlyphOrder
topDictData = TopDictIndex(None, cff2GetGlyphOrder)
topDictData.items = self.topDictIndex.items
self.topDictIndex = topDictData
topDict = topDictData[0]
if hasattr(topDict, "Private"):
privateDict = topDict.Private
else:
privateDict = None
opOrder = buildOrder(topDictOperators2)
topDict.order = opOrder
topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
if not hasattr(topDict, "FDArray"): def convertCFF2ToCFF(self, otFont):
fdArray = topDict.FDArray = FDArrayIndex() from .CFF2ToCFF import _convertCFF2ToCFF
fdArray.strings = None
fdArray.GlobalSubrs = topDict.GlobalSubrs
topDict.GlobalSubrs.fdArray = fdArray
charStrings = topDict.CharStrings
if charStrings.charStringsAreIndexed:
charStrings.charStringsIndex.fdArray = fdArray
else:
charStrings.fdArray = fdArray
fontDict = FontDict()
fontDict.setCFF2(True)
fdArray.append(fontDict)
fontDict.Private = privateDict
privateOpOrder = buildOrder(privateDictOperators2)
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
else:
# clean up the PrivateDicts in the fdArray
fdArray = topDict.FDArray
privateOpOrder = buildOrder(privateDictOperators2)
for fontDict in fdArray:
fontDict.setCFF2(True)
for key in fontDict.rawDict.keys():
if key not in fontDict.order:
del fontDict.rawDict[key]
if hasattr(fontDict, key):
delattr(fontDict, key)
privateDict = fontDict.Private _convertCFF2ToCFF(self, otFont)
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
# At this point, the Subrs and Charstrings are all still T2Charstring class
# easiest to fix this by compiling, then decompiling again
file = BytesIO()
self.compile(file, otFont, isCFF2=True)
file.seek(0)
self.decompile(file, otFont, isCFF2=True)
def desubroutinize(self): def desubroutinize(self):
for fontName in self.fontNames: for fontName in self.fontNames:
font = self[fontName] font = self[fontName]
cs = font.CharStrings cs = font.CharStrings
for g in font.charset: for c in cs.values():
c, _ = cs.getItemAndSelector(g)
c.decompile() c.decompile()
subrs = getattr(c.private, "Subrs", []) subrs = getattr(c.private, "Subrs", [])
decompiler = _DesubroutinizingT2Decompiler( decompiler = _DesubroutinizingT2Decompiler(
@ -764,8 +690,8 @@ class Index(object):
compilerClass = IndexCompiler compilerClass = IndexCompiler
def __init__(self, file=None, isCFF2=None): def __init__(self, file=None, isCFF2=None):
assert (isCFF2 is None) == (file is None)
self.items = [] self.items = []
self.offsets = offsets = []
name = self.__class__.__name__ name = self.__class__.__name__
if file is None: if file is None:
return return
@ -782,7 +708,6 @@ class Index(object):
offSize = readCard8(file) offSize = readCard8(file)
log.log(DEBUG, " index count: %s offSize: %s", count, offSize) log.log(DEBUG, " index count: %s offSize: %s", count, offSize)
assert offSize <= 4, "offSize too large: %s" % offSize assert offSize <= 4, "offSize too large: %s" % offSize
self.offsets = offsets = []
pad = b"\0" * (4 - offSize) pad = b"\0" * (4 - offSize)
for index in range(count + 1): for index in range(count + 1):
chunk = file.read(offSize) chunk = file.read(offSize)
@ -960,7 +885,6 @@ class TopDictIndex(Index):
compilerClass = TopDictIndexCompiler compilerClass = TopDictIndexCompiler
def __init__(self, file=None, cff2GetGlyphOrder=None, topSize=0, isCFF2=None): def __init__(self, file=None, cff2GetGlyphOrder=None, topSize=0, isCFF2=None):
assert (isCFF2 is None) == (file is None)
self.cff2GetGlyphOrder = cff2GetGlyphOrder self.cff2GetGlyphOrder = cff2GetGlyphOrder
if file is not None and isCFF2: if file is not None and isCFF2:
self._isCFF2 = isCFF2 self._isCFF2 = isCFF2
@ -2861,9 +2785,11 @@ class PrivateDict(BaseDict):
# Provide dummy values. This avoids needing to provide # Provide dummy values. This avoids needing to provide
# an isCFF2 state in a lot of places. # an isCFF2 state in a lot of places.
self.nominalWidthX = self.defaultWidthX = None self.nominalWidthX = self.defaultWidthX = None
self._isCFF2 = True
else: else:
self.defaults = buildDefaults(privateDictOperators) self.defaults = buildDefaults(privateDictOperators)
self.order = buildOrder(privateDictOperators) self.order = buildOrder(privateDictOperators)
self._isCFF2 = False
@property @property
def in_cff2(self): def in_cff2(self):

View File

@ -43,10 +43,8 @@ def programToCommands(program, getNumRegions=None):
hintmask/cntrmask argument, as well as stray arguments at the end of the hintmask/cntrmask argument, as well as stray arguments at the end of the
program (🤷). program (🤷).
'getNumRegions' may be None, or a callable object. It must return the 'getNumRegions' may be None, or a callable object. It must return the
number of regions. 'getNumRegions' takes a single argument, vsindex. If number of regions. 'getNumRegions' takes a single argument, vsindex. It
the vsindex argument is None, getNumRegions returns the default number returns the numRegions for the vsindex.
of regions for the charstring, else it returns the numRegions for
the vsindex.
The Charstring may or may not start with a width value. If the first The Charstring may or may not start with a width value. If the first
non-blend operator has an odd number of arguments, then the first argument is non-blend operator has an odd number of arguments, then the first argument is
a width, and is popped off. This is complicated with blend operators, as a width, and is popped off. This is complicated with blend operators, as
@ -61,7 +59,7 @@ def programToCommands(program, getNumRegions=None):
""" """
seenWidthOp = False seenWidthOp = False
vsIndex = None vsIndex = 0
lenBlendStack = 0 lenBlendStack = 0
lastBlendIndex = 0 lastBlendIndex = 0
commands = [] commands = []

View File

@ -13,6 +13,9 @@ from operator import add
from functools import reduce from functools import reduce
__all__ = ["optimizeWidths", "main"]
class missingdict(dict): class missingdict(dict):
def __init__(self, missing_func): def __init__(self, missing_func):
self.missing_func = missing_func self.missing_func = missing_func

View File

@ -294,6 +294,8 @@ def merge(self, m, tables):
extractor.execute(c) extractor.execute(c)
width = extractor.width width = extractor.width
if width is not defaultWidthXToken: if width is not defaultWidthXToken:
# The following will be wrong if the width is added
# by a subroutine. Ouch!
c.program.pop(0) c.program.pop(0)
else: else:
width = defaultWidthX width = defaultWidthX

View File

@ -537,7 +537,7 @@ class TTFont(object):
# #
# Not enough names found in the 'post' table. # Not enough names found in the 'post' table.
# Can happen when 'post' format 1 is improperly used on a font that # Can happen when 'post' format 1 is improperly used on a font that
# has more than 258 glyphs (the lenght of 'standardGlyphOrder'). # has more than 258 glyphs (the length of 'standardGlyphOrder').
# #
log.warning( log.warning(
"Not enough names found in the 'post' table, generating them from cmap instead" "Not enough names found in the 'post' table, generating them from cmap instead"

View File

@ -845,9 +845,10 @@ def _add_CFF2(varFont, model, master_fonts):
glyphOrder = varFont.getGlyphOrder() glyphOrder = varFont.getGlyphOrder()
if "CFF2" not in varFont: if "CFF2" not in varFont:
from .cff import convertCFFtoCFF2 from fontTools.cffLib.CFFToCFF2 import convertCFFToCFF2
convertCFFToCFF2(varFont)
convertCFFtoCFF2(varFont)
ordered_fonts_list = model.reorderMasters(master_fonts, model.reverseMapping) ordered_fonts_list = model.reorderMasters(master_fonts, model.reverseMapping)
# re-ordering the master list simplifies building the CFF2 data item lists. # re-ordering the master list simplifies building the CFF2 data item lists.
merge_region_fonts(varFont, model, ordered_fonts_list, glyphOrder) merge_region_fonts(varFont, model, ordered_fonts_list, glyphOrder)

View File

@ -49,95 +49,6 @@ def addCFFVarStore(varFont, varModel, varDataList, masterSupports):
fontDict.Private.vstore = topDict.VarStore fontDict.Private.vstore = topDict.VarStore
def lib_convertCFFToCFF2(cff, otFont):
# This assumes a decompiled CFF table.
cff2GetGlyphOrder = cff.otFont.getGlyphOrder
topDictData = TopDictIndex(None, cff2GetGlyphOrder, None)
topDictData.items = cff.topDictIndex.items
cff.topDictIndex = topDictData
topDict = topDictData[0]
if hasattr(topDict, "Private"):
privateDict = topDict.Private
else:
privateDict = None
opOrder = buildOrder(topDictOperators2)
topDict.order = opOrder
topDict.cff2GetGlyphOrder = cff2GetGlyphOrder
if not hasattr(topDict, "FDArray"):
fdArray = topDict.FDArray = FDArrayIndex()
fdArray.strings = None
fdArray.GlobalSubrs = topDict.GlobalSubrs
topDict.GlobalSubrs.fdArray = fdArray
charStrings = topDict.CharStrings
if charStrings.charStringsAreIndexed:
charStrings.charStringsIndex.fdArray = fdArray
else:
charStrings.fdArray = fdArray
fontDict = FontDict()
fontDict.setCFF2(True)
fdArray.append(fontDict)
fontDict.Private = privateDict
privateOpOrder = buildOrder(privateDictOperators2)
if privateDict is not None:
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
else:
# clean up the PrivateDicts in the fdArray
fdArray = topDict.FDArray
privateOpOrder = buildOrder(privateDictOperators2)
for fontDict in fdArray:
fontDict.setCFF2(True)
for key in list(fontDict.rawDict.keys()):
if key not in fontDict.order:
del fontDict.rawDict[key]
if hasattr(fontDict, key):
delattr(fontDict, key)
privateDict = fontDict.Private
for entry in privateDictOperators:
key = entry[1]
if key not in privateOpOrder:
if key in privateDict.rawDict:
# print "Removing private dict", key
del privateDict.rawDict[key]
if hasattr(privateDict, key):
delattr(privateDict, key)
# print "Removing privateDict attr", key
# Now delete up the deprecated topDict operators from CFF 1.0
for entry in topDictOperators:
key = entry[1]
if key not in opOrder:
if key in topDict.rawDict:
del topDict.rawDict[key]
if hasattr(topDict, key):
delattr(topDict, key)
# At this point, the Subrs and Charstrings are all still T2Charstring class
# easiest to fix this by compiling, then decompiling again
cff.major = 2
file = BytesIO()
cff.compile(file, otFont, isCFF2=True)
file.seek(0)
cff.decompile(file, otFont, isCFF2=True)
def convertCFFtoCFF2(varFont):
# Convert base font to a single master CFF2 font.
cffTable = varFont["CFF "]
lib_convertCFFToCFF2(cffTable.cff, varFont)
newCFF2 = newTable("CFF2")
newCFF2.cff = cffTable.cff
varFont["CFF2"] = newCFF2
del varFont["CFF "]
def conv_to_int(num): def conv_to_int(num):
if isinstance(num, float) and num.is_integer(): if isinstance(num, float) and num.is_integer():
return int(num) return int(num)

View File

@ -89,7 +89,7 @@ from fontTools.misc.fixedTools import (
otRound, otRound,
) )
from fontTools.varLib.models import normalizeValue, piecewiseLinearMap from fontTools.varLib.models import normalizeValue, piecewiseLinearMap
from fontTools.ttLib import TTFont from fontTools.ttLib import TTFont, newTable
from fontTools.ttLib.tables.TupleVariation import TupleVariation from fontTools.ttLib.tables.TupleVariation import TupleVariation
from fontTools.ttLib.tables import _g_l_y_f from fontTools.ttLib.tables import _g_l_y_f
from fontTools import varLib from fontTools import varLib
@ -97,6 +97,13 @@ from fontTools import varLib
# we import the `subset` module because we use the `prune_lookups` method on the GSUB # we import the `subset` module because we use the `prune_lookups` method on the GSUB
# table class, and that method is only defined dynamically upon importing `subset` # table class, and that method is only defined dynamically upon importing `subset`
from fontTools import subset # noqa: F401 from fontTools import subset # noqa: F401
from fontTools.cffLib import privateDictOperators2
from fontTools.cffLib.specializer import (
programToCommands,
commandsToProgram,
specializeCommands,
generalizeCommands,
)
from fontTools.varLib import builder from fontTools.varLib import builder
from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib.mvar import MVAR_ENTRIES
from fontTools.varLib.merger import MutatorMerger from fontTools.varLib.merger import MutatorMerger
@ -566,6 +573,259 @@ def changeTupleVariationAxisLimit(var, axisTag, axisLimit):
return out return out
def instantiateCFF2(
varfont,
axisLimits,
*,
round=round,
specialize=True,
generalize=False,
downgrade=False,
):
# The algorithm here is rather simple:
#
# Take all blend operations and store their deltas in the (otherwise empty)
# CFF2 VarStore. Then, instantiate the VarStore with the given axis limits,
# and read back the new deltas. This is done for both the CharStrings and
# the Private dicts.
#
# Then prune unused things and possibly drop the VarStore if it's empty.
# In which case, downgrade to CFF table if requested.
log.info("Instantiating CFF2 table")
fvarAxes = varfont["fvar"].axes
cff = varfont["CFF2"].cff
topDict = cff.topDictIndex[0]
varStore = topDict.VarStore.otVarStore
if not varStore:
if downgrade:
from fontTools.cffLib.CFF2ToCFF import convertCFF2ToCFF
convertCFF2ToCFF(varfont)
return
cff.desubroutinize()
def getNumRegions(vsindex):
return varStore.VarData[vsindex if vsindex is not None else 0].VarRegionCount
charStrings = topDict.CharStrings.values()
# Gather all unique private dicts
uniquePrivateDicts = set()
privateDicts = []
for fd in topDict.FDArray:
if fd.Private not in uniquePrivateDicts:
uniquePrivateDicts.add(fd.Private)
privateDicts.append(fd.Private)
allCommands = []
for cs in charStrings:
assert cs.private.vstore.otVarStore is varStore # Or in many places!!
commands = programToCommands(cs.program, getNumRegions=getNumRegions)
if generalize:
commands = generalizeCommands(commands)
if specialize:
commands = specializeCommands(commands, generalizeFirst=not generalize)
allCommands.append(commands)
def storeBlendsToVarStore(arg):
if not isinstance(arg, list):
return
if any(isinstance(subarg, list) for subarg in arg[:-1]):
raise NotImplementedError("Nested blend lists not supported (yet)")
count = arg[-1]
assert (len(arg) - 1) % count == 0
nRegions = (len(arg) - 1) // count - 1
assert nRegions == getNumRegions(vsindex)
for i in range(count, len(arg) - 1, nRegions):
deltas = arg[i : i + nRegions]
assert len(deltas) == nRegions
varData = varStore.VarData[vsindex]
varData.Item.append(deltas)
varData.ItemCount += 1
def fetchBlendsFromVarStore(arg):
if not isinstance(arg, list):
return [arg]
if any(isinstance(subarg, list) for subarg in arg[:-1]):
raise NotImplementedError("Nested blend lists not supported (yet)")
count = arg[-1]
assert (len(arg) - 1) % count == 0
numRegions = getNumRegions(vsindex)
newDefaults = []
newDeltas = []
for i in range(count):
defaultValue = arg[i]
major = vsindex
minor = varDataCursor[major]
varDataCursor[major] += 1
varIdx = (major << 16) + minor
defaultValue += round(defaultDeltas[varIdx])
newDefaults.append(defaultValue)
varData = varStore.VarData[major]
deltas = varData.Item[minor]
assert len(deltas) == numRegions
newDeltas.extend(deltas)
if not numRegions:
return newDefaults # No deltas, just return the defaults
return [newDefaults + newDeltas + [count]]
# Check VarData's are empty
for varData in varStore.VarData:
assert varData.Item == []
assert varData.ItemCount == 0
# Add charstring blend lists to VarStore so we can instantiate them
for commands in allCommands:
vsindex = 0
for command in commands:
if command[0] == "vsindex":
vsindex = command[1][0]
continue
for arg in command[1]:
storeBlendsToVarStore(arg)
# Add private blend lists to VarStore so we can instantiate values
vsindex = 0
for opcode, name, arg_type, default, converter in privateDictOperators2:
if arg_type not in ("number", "delta", "array"):
continue
vsindex = 0
for private in privateDicts:
if not hasattr(private, name):
continue
values = getattr(private, name)
if name == "vsindex":
vsindex = values[0]
continue
if arg_type == "number":
values = [values]
for value in values:
if not isinstance(value, list):
continue
assert len(value) % (getNumRegions(vsindex) + 1) == 0
count = len(value) // (getNumRegions(vsindex) + 1)
storeBlendsToVarStore(value + [count])
# Instantiate VarStore
defaultDeltas = instantiateItemVariationStore(varStore, fvarAxes, axisLimits)
# Read back new charstring blends from the instantiated VarStore
varDataCursor = [0] * len(varStore.VarData)
for commands in allCommands:
vsindex = 0
for command in commands:
if command[0] == "vsindex":
vsindex = command[1][0]
continue
newArgs = []
for arg in command[1]:
newArgs.extend(fetchBlendsFromVarStore(arg))
command[1][:] = newArgs
# Read back new private blends from the instantiated VarStore
for opcode, name, arg_type, default, converter in privateDictOperators2:
if arg_type not in ("number", "delta", "array"):
continue
for private in privateDicts:
if not hasattr(private, name):
continue
values = getattr(private, name)
if arg_type == "number":
values = [values]
newValues = []
for value in values:
if not isinstance(value, list):
newValues.append(value)
continue
value.append(1)
value = fetchBlendsFromVarStore(value)
newValues.extend(v[:-1] if isinstance(v, list) else v for v in value)
if arg_type == "number":
newValues = newValues[0]
setattr(private, name, newValues)
# Empty out the VarStore
for i, varData in enumerate(varStore.VarData):
assert varDataCursor[i] == varData.ItemCount, (
varDataCursor[i],
varData.ItemCount,
)
varData.Item = []
varData.ItemCount = 0
# Remove vsindex commands that are no longer needed, collect those that are.
usedVsindex = set()
for commands in allCommands:
if any(isinstance(arg, list) for command in commands for arg in command[1]):
vsindex = 0
for command in commands:
if command[0] == "vsindex":
vsindex = command[1][0]
continue
if any(isinstance(arg, list) for arg in command[1]):
usedVsindex.add(vsindex)
else:
commands[:] = [command for command in commands if command[0] != "vsindex"]
# Remove unused VarData and update vsindex values
vsindexMapping = {v: i for i, v in enumerate(sorted(usedVsindex))}
varStore.VarData = [
varData for i, varData in enumerate(varStore.VarData) if i in usedVsindex
]
varStore.VarDataCount = len(varStore.VarData)
for commands in allCommands:
for command in commands:
if command[0] == "vsindex":
command[1][0] = vsindexMapping[command[1][0]]
# Remove initial vsindex commands that are implied
for commands in allCommands:
if commands and commands[0] == ("vsindex", [0]):
commands.pop(0)
# Ship the charstrings!
for cs, commands in zip(charStrings, allCommands):
cs.program = commandsToProgram(commands)
# Remove empty VarStore
if not varStore.VarData:
if "VarStore" in topDict.rawDict:
del topDict.rawDict["VarStore"]
del topDict.VarStore
del topDict.CharStrings.varStore
for private in privateDicts:
del private.vstore
if downgrade:
from fontTools.cffLib.CFF2ToCFF import convertCFF2ToCFF
convertCFF2ToCFF(varfont)
def _instantiateGvarGlyph( def _instantiateGvarGlyph(
glyphname, glyf, gvar, hMetrics, vMetrics, axisLimits, optimize=True glyphname, glyf, gvar, hMetrics, vMetrics, axisLimits, optimize=True
): ):
@ -765,22 +1025,57 @@ def _remapVarIdxMap(table, attrName, varIndexMapping, glyphOrder):
# TODO(anthrotype) Add support for HVAR/VVAR in CFF2 # TODO(anthrotype) Add support for HVAR/VVAR in CFF2
def _instantiateVHVAR(varfont, axisLimits, tableFields): def _instantiateVHVAR(varfont, axisLimits, tableFields, *, round=round):
location = axisLimits.pinnedLocation() location = axisLimits.pinnedLocation()
tableTag = tableFields.tableTag tableTag = tableFields.tableTag
fvarAxes = varfont["fvar"].axes fvarAxes = varfont["fvar"].axes
# Deltas from gvar table have already been applied to the hmtx/vmtx. For full
# instances (i.e. all axes pinned), we can simply drop HVAR/VVAR and return
if set(location).issuperset(axis.axisTag for axis in fvarAxes):
log.info("Dropping %s table", tableTag)
del varfont[tableTag]
return
log.info("Instantiating %s table", tableTag) log.info("Instantiating %s table", tableTag)
vhvar = varfont[tableTag].table vhvar = varfont[tableTag].table
varStore = vhvar.VarStore varStore = vhvar.VarStore
# since deltas were already applied, the return value here is ignored
instantiateItemVariationStore(varStore, fvarAxes, axisLimits) if "glyf" in varfont:
# Deltas from gvar table have already been applied to the hmtx/vmtx. For full
# instances (i.e. all axes pinned), we can simply drop HVAR/VVAR and return
if set(location).issuperset(axis.axisTag for axis in fvarAxes):
log.info("Dropping %s table", tableTag)
del varfont[tableTag]
return
defaultDeltas = instantiateItemVariationStore(varStore, fvarAxes, axisLimits)
if "glyf" not in varfont:
# CFF2 fonts need hmtx/vmtx updated here. For glyf fonts, the instantiateGvar
# function already updated the hmtx/vmtx from phantom points. Maybe remove
# that and do it here for both CFF2 and glyf fonts?
#
# Specially, if a font has glyf but not gvar, the hmtx/vmtx will not have been
# updated by instantiateGvar. Though one can call that a faulty font.
metricsTag = "vmtx" if tableTag == "VVAR" else "hmtx"
if metricsTag in varfont:
advMapping = getattr(vhvar, tableFields.advMapping)
metricsTable = varfont[metricsTag]
metrics = metricsTable.metrics
for glyphName, (advanceWidth, sb) in metrics.items():
if advMapping:
varIdx = advMapping.mapping[glyphName]
else:
varIdx = varfont.getGlyphID(glyphName)
metrics[glyphName] = (advanceWidth + round(defaultDeltas[varIdx]), sb)
if (
tableTag == "VVAR"
and getattr(vhvar, tableFields.vOrigMapping) is not None
):
log.warning(
"VORG table not yet updated to reflect changes in VVAR table"
)
# For full instances (i.e. all axes pinned), we can simply drop HVAR/VVAR and return
if set(location).issuperset(axis.axisTag for axis in fvarAxes):
log.info("Dropping %s table", tableTag)
del varfont[tableTag]
return
if varStore.VarRegionList.Region: if varStore.VarRegionList.Region:
# Only re-optimize VarStore if the HVAR/VVAR already uses indirect AdvWidthMap # Only re-optimize VarStore if the HVAR/VVAR already uses indirect AdvWidthMap
@ -923,6 +1218,8 @@ def instantiateItemVariationStore(itemVarStore, fvarAxes, axisLimits):
newItemVarStore = tupleVarStore.asItemVarStore() newItemVarStore = tupleVarStore.asItemVarStore()
itemVarStore.VarRegionList = newItemVarStore.VarRegionList itemVarStore.VarRegionList = newItemVarStore.VarRegionList
if not hasattr(itemVarStore, "VarDataCount"): # Happens fromXML
itemVarStore.VarDataCount = len(newItemVarStore.VarData)
assert itemVarStore.VarDataCount == newItemVarStore.VarDataCount assert itemVarStore.VarDataCount == newItemVarStore.VarDataCount
itemVarStore.VarData = newItemVarStore.VarData itemVarStore.VarData = newItemVarStore.VarData
@ -1222,9 +1519,6 @@ def sanityCheckVariableTables(varfont):
if "gvar" in varfont: if "gvar" in varfont:
if "glyf" not in varfont: if "glyf" not in varfont:
raise ValueError("Can't have gvar without glyf") raise ValueError("Can't have gvar without glyf")
# TODO(anthrotype) Remove once we do support partial instancing CFF2
if "CFF2" in varfont:
raise NotImplementedError("Instancing CFF2 variable fonts is not supported yet")
def instantiateVariableFont( def instantiateVariableFont(
@ -1234,6 +1528,8 @@ def instantiateVariableFont(
optimize=True, optimize=True,
overlap=OverlapMode.KEEP_AND_SET_FLAGS, overlap=OverlapMode.KEEP_AND_SET_FLAGS,
updateFontNames=False, updateFontNames=False,
*,
downgradeCFF2=False,
): ):
"""Instantiate variable font, either fully or partially. """Instantiate variable font, either fully or partially.
@ -1273,6 +1569,11 @@ def instantiateVariableFont(
in the head and OS/2 table will be updated so they conform to the R/I/B/BI in the head and OS/2 table will be updated so they conform to the R/I/B/BI
model. If the STAT table is missing or an Axis Value table is missing for model. If the STAT table is missing or an Axis Value table is missing for
a given axis coordinate, a ValueError will be raised. a given axis coordinate, a ValueError will be raised.
downgradeCFF2 (bool): if True, downgrade the CFF2 table to CFF table when possible
ie. full instancing of all axes. This is useful for compatibility with older
software that does not support CFF2. Defaults to False. Note that this
operation also removes overlaps within glyph shapes, as CFF does not support
overlaps but CFF2 does.
""" """
# 'overlap' used to be bool and is now enum; for backward compat keep accepting bool # 'overlap' used to be bool and is now enum; for backward compat keep accepting bool
overlap = OverlapMode(int(overlap)) overlap = OverlapMode(int(overlap))
@ -1297,6 +1598,9 @@ def instantiateVariableFont(
log.info("Updating name table") log.info("Updating name table")
names.updateNameTable(varfont, axisLimits) names.updateNameTable(varfont, axisLimits)
if "CFF2" in varfont:
instantiateCFF2(varfont, normalizedLimits, downgrade=downgradeCFF2)
if "gvar" in varfont: if "gvar" in varfont:
instantiateGvar(varfont, normalizedLimits, optimize=optimize) instantiateGvar(varfont, normalizedLimits, optimize=optimize)
@ -1488,6 +1792,11 @@ def parseArgs(args):
help="Update the instantiated font's `name` table. Input font must have " help="Update the instantiated font's `name` table. Input font must have "
"a STAT table with Axis Value Tables", "a STAT table with Axis Value Tables",
) )
parser.add_argument(
"--downgrade-cff2",
action="store_true",
help="If all axes are pinned, downgrade CFF2 to CFF table format",
)
parser.add_argument( parser.add_argument(
"--no-recalc-timestamp", "--no-recalc-timestamp",
dest="recalc_timestamp", dest="recalc_timestamp",
@ -1559,6 +1868,7 @@ def main(args=None):
optimize=options.optimize, optimize=options.optimize,
overlap=options.overlap, overlap=options.overlap,
updateFontNames=options.update_name_table, updateFontNames=options.update_name_table,
downgradeCFF2=options.downgrade_cff2,
) )
suffix = "-instance" if isFullInstance else "-partial" suffix = "-instance" if isFullInstance else "-partial"

View File

@ -330,9 +330,9 @@ def test_build_cff_to_cff2(tmpdir):
} }
fb.setupCFF("TestFont", {}, charStrings, {}) fb.setupCFF("TestFont", {}, charStrings, {})
from fontTools.varLib.cff import convertCFFtoCFF2 from fontTools.cffLib.CFFToCFF2 import convertCFFToCFF2
convertCFFtoCFF2(fb.font) convertCFFToCFF2(fb.font)
def test_setupNameTable_no_mac(): def test_setupNameTable_no_mac():

View File

@ -0,0 +1,729 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="hyphen"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.004"/>
<checkSumAdjustment value="0x9cb1a5ae"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Apr 29 17:39:47 2021"/>
<modified value="Thu Apr 29 08:51:43 2021"/>
<xMin value="-991"/>
<yMin value="-1050"/>
<xMax value="2930"/>
<yMax value="1810"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1160"/>
<descent value="-288"/>
<lineGap value="0"/>
<advanceWidthMax value="3000"/>
<minLeftSideBearing value="-991"/>
<minRightSideBearing value="-519"/>
<xMaxExtent value="2930"/>
<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>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="3"/>
<xAvgCharWidth value="989"/>
<usWeightClass value="100"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
<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="325"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="11"/>
<bWeight value="2"/>
<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="ADBO"/>
<fsSelection value="00000000 00000000"/>
<usFirstCharIndex value="45"/>
<usLastCharIndex value="45"/>
<sTypoAscender value="880"/>
<sTypoDescender value="-120"/>
<sTypoLineGap value="0"/>
<usWinAscent value="1160"/>
<usWinDescent value="288"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="543"/>
<sCapHeight value="733"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="6"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="1000" lsb="100"/>
<mtx name="hyphen" width="324" lsb="44"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x2d" name="hyphen"/><!-- HYPHEN-MINUS -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x2d" name="hyphen"/><!-- HYPHEN-MINUS -->
</cmap_format_4>
</cmap>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
© 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
2.004;ADBO;NotoSansSC-Thin;ADOBE
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.004;hotconv 1.0.118;makeotfexe 2.5.65603
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
DemiLight
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
Medium
</namerecord>
<namerecord nameID="263" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="264" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
<namerecord nameID="265" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="266" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="267" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="268" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="269" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Light
</namerecord>
<namerecord nameID="270" platformID="3" platEncID="1" langID="0x409">
DemiLight
</namerecord>
<namerecord nameID="271" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-DemiLight
</namerecord>
<namerecord nameID="272" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="273" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Regular
</namerecord>
<namerecord nameID="274" platformID="3" platEncID="1" langID="0x409">
Medium
</namerecord>
<namerecord nameID="275" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Medium
</namerecord>
<namerecord nameID="276" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="277" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Bold
</namerecord>
<namerecord nameID="278" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
<namerecord nameID="279" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Black
</namerecord>
</name>
<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-125"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDSelect format="0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
<FontDict index="1">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef" fdSelectIndex="0">
</CharString>
<CharString name="hyphen" fdSelectIndex="1">
44 256 6 -29 2 blend
rmoveto
239 35 -239 44 90 -44 3 blend
hlineto
</CharString>
</CharStrings>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
</VarData>
</VarStore>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="0"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="1"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="2"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="3"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="4"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="5"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=6 -->
<FeatureRecord index="0">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="1">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="2">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="3">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="4">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="5">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
</FeatureList>
<LookupList>
<!-- LookupCount=1 -->
<Lookup index="0">
<LookupType value="2"/>
<LookupFlag value="0"/>
<!-- SubTableCount=1 -->
<PairPos index="0" Format="2">
<Coverage>
<Glyph value="hyphen"/>
</Coverage>
<ValueFormat1 value="68"/>
<ValueFormat2 value="0"/>
<ClassDef1>
</ClassDef1>
<ClassDef2>
<ClassDef glyph="hyphen" class="1"/>
</ClassDef2>
<!-- Class1Count=1 -->
<!-- Class2Count=2 -->
<Class1Record index="0">
<Class2Record index="0">
<Value1 XAdvance="0"/>
</Class2Record>
<Class2Record index="1">
<Value1 XAdvance="0"/>
</Class2Record>
</Class1Record>
</PairPos>
</Lookup>
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=2 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
<Item index="0" value="[0]"/>
<Item index="1" value="[59]"/>
</VarData>
</VarStore>
</HVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="265"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=7 -->
<AxisValueArray>
<AxisValue index="0" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="258"/> <!-- Thin -->
<NominalValue value="100.0"/>
<RangeMinValue value="100.0"/>
<RangeMaxValue value="199.0"/>
</AxisValue>
<AxisValue index="1" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="259"/> <!-- Light -->
<NominalValue value="300.0"/>
<RangeMinValue value="200.0"/>
<RangeMaxValue value="349.0"/>
</AxisValue>
<AxisValue index="2" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="260"/> <!-- DemiLight -->
<NominalValue value="350.0"/>
<RangeMinValue value="350.0"/>
<RangeMaxValue value="399.0"/>
</AxisValue>
<AxisValue index="3" Format="2">
<AxisIndex value="0"/>
<Flags value="2"/> <!-- ElidableAxisValueName -->
<ValueNameID value="261"/> <!-- Regular -->
<NominalValue value="400.0"/>
<RangeMinValue value="400.0"/>
<RangeMaxValue value="499.0"/>
</AxisValue>
<AxisValue index="4" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="262"/> <!-- Medium -->
<NominalValue value="500.0"/>
<RangeMinValue value="500.0"/>
<RangeMaxValue value="650.0"/>
</AxisValue>
<AxisValue index="5" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="263"/> <!-- Bold -->
<NominalValue value="700.0"/>
<RangeMinValue value="650.0"/>
<RangeMaxValue value="800.0"/>
</AxisValue>
<AxisValue index="6" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="264"/> <!-- Black -->
<NominalValue value="900.0"/>
<RangeMinValue value="800.0"/>
<RangeMaxValue value="900.0"/>
</AxisValue>
</AxisValueArray>
<ElidedFallbackNameID value="256"/> <!-- Regular -->
</STAT>
<VORG>
<majorVersion value="1"/>
<minorVersion value="0"/>
<defaultVertOriginY value="880"/>
<numVertOriginYMetrics value="0"/>
</VORG>
<VVAR>
<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>
<AdvHeightMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="hyphen" outer="0" inner="0"/>
</AdvHeightMap>
<VOrgMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="hyphen" outer="0" inner="0"/>
</VOrgMap>
</VVAR>
<avar>
<version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
<mapping from="0.25" to="0.16"/>
<mapping from="0.3125" to="0.32"/>
<mapping from="0.375" to="0.39"/>
<mapping from="0.5" to="0.56"/>
<mapping from="0.75" to="0.78"/>
<mapping from="1.0" to="1.0"/>
</segment>
</avar>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>100.0</MinValue>
<DefaultValue>100.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<AxisNameID>265</AxisNameID>
</Axis>
<!-- Thin -->
<!-- PostScript: NotoSansSC-Thin -->
<NamedInstance flags="0x0" postscriptNameID="267" subfamilyNameID="266">
<coord axis="wght" value="100.0"/>
</NamedInstance>
<!-- Light -->
<!-- PostScript: NotoSansSC-Light -->
<NamedInstance flags="0x0" postscriptNameID="269" subfamilyNameID="268">
<coord axis="wght" value="300.0"/>
</NamedInstance>
<!-- DemiLight -->
<!-- PostScript: NotoSansSC-DemiLight -->
<NamedInstance flags="0x0" postscriptNameID="271" subfamilyNameID="270">
<coord axis="wght" value="350.0"/>
</NamedInstance>
<!-- Regular -->
<!-- PostScript: NotoSansSC-Regular -->
<NamedInstance flags="0x0" postscriptNameID="273" subfamilyNameID="272">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Medium -->
<!-- PostScript: NotoSansSC-Medium -->
<NamedInstance flags="0x0" postscriptNameID="275" subfamilyNameID="274">
<coord axis="wght" value="500.0"/>
</NamedInstance>
<!-- Bold -->
<!-- PostScript: NotoSansSC-Bold -->
<NamedInstance flags="0x0" postscriptNameID="277" subfamilyNameID="276">
<coord axis="wght" value="700.0"/>
</NamedInstance>
<!-- Black -->
<!-- PostScript: NotoSansSC-Black -->
<NamedInstance flags="0x0" postscriptNameID="279" subfamilyNameID="278">
<coord axis="wght" value="900.0"/>
</NamedInstance>
</fvar>
<vhea>
<tableVersion value="0x00011000"/>
<ascent value="500"/>
<descent value="-500"/>
<lineGap value="0"/>
<advanceHeightMax value="3000"/>
<minTopSideBearing value="-172"/>
<minBottomSideBearing value="-648"/>
<yMaxExtent value="2930"/>
<caretSlopeRise value="0"/>
<caretSlopeRun value="1"/>
<caretOffset value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<reserved4 value="0"/>
<metricDataFormat value="0"/>
<numberOfVMetrics value="1"/>
</vhea>
<vmtx>
<mtx name=".notdef" height="1000" tsb="0"/>
<mtx name="hyphen" height="1000" tsb="589"/>
</vmtx>
</ttFont>

View File

@ -0,0 +1,615 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<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="1.002"/>
<checkSumAdjustment value="0x3580d06e"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Sep 15 20:38:06 2022"/>
<modified value="Thu Sep 15 20:38:06 2022"/>
<xMin value="20"/>
<yMin value="0"/>
<xMax value="376"/>
<yMax value="700"/>
<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="500"/>
<minLeftSideBearing value="20"/>
<minRightSideBearing value="20"/>
<xMaxExtent value="376"/>
<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>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="379"/>
<usWeightClass value="100"/>
<usWidthClass value="1"/>
<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="LTTR"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="65"/>
<usLastCharIndex value="65"/>
<sTypoAscender value="700"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="300"/>
<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="2"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="396" lsb="20"/>
</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>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
License same as MutatorMath. BSD 3-clause. [test-token: C]
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.002;LTTR;MutatorMathTest-LightCondensed
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
MutatorMathTest LightCondensed
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.002
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
MutatorMathTest-LightCondensed
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Width
</namerecord>
<namerecord nameID="257" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
width
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
weight
</namerecord>
</name>
<post>
<formatType value="3.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"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
<Subrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
<CharString index="0">
1 blend
hlineto
</CharString>
<CharString index="1">
2 blend
rmoveto
</CharString>
<CharString index="2">
3 blend
hlineto
</CharString>
<CharString index="3">
1 blend
hmoveto
</CharString>
<CharString index="4">
0 100 0 2 blend
rlineto
</CharString>
<CharString index="5">
1 vsindex
20 30 -30 0 -104 callsubr
40 7 220 63 -107 callsubr
140 700 375 -56 -169 -103 callsubr
-35 -7 -195 -43 -107 callsubr
-90 -536 -235 96 79 60 -144 -60 -106 callsubr
250 36 -250 450 220 -190 -6 174 16 -450 -220 190 -105 callsubr
257 -200 585 23 -275 -54 -130 44 -106 callsubr
44 9 296 121 -107 callsubr
-145 700 -375 29 151 -103 callsubr
-39 -9 -281 -121 -107 callsubr
-17 -39 15 -73 5 3 -221 -3 -106 callsubr
47 39 -47 3 223 147 -3 221 3 -3 -223 -147 -105 callsubr
</CharString>
</Subrs>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef">
</CharString>
<CharString name="A">
-102 callsubr
</CharString>
</CharStrings>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
<!-- RegionCount=8 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
<Region index="1">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.63574"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="2">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.63574"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="3">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.63574"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="4">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.63574"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="5">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.5691"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.63574"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="6">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="7">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=5 -->
<VarData index="0">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=6 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="1"/>
<VarRegionIndex index="2" value="2"/>
<VarRegionIndex index="3" value="3"/>
<VarRegionIndex index="4" value="4"/>
<VarRegionIndex index="5" value="5"/>
</VarData>
<VarData index="1">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=3 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="6"/>
<VarRegionIndex index="2" value="7"/>
</VarData>
<VarData index="2">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=4 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="1"/>
<VarRegionIndex index="2" value="2"/>
<VarRegionIndex index="3" value="7"/>
</VarData>
<VarData index="3">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=4 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="6"/>
<VarRegionIndex index="2" value="7"/>
<VarRegionIndex index="3" value="3"/>
</VarData>
<VarData index="4">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=5 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="6"/>
<VarRegionIndex index="2" value="7"/>
<VarRegionIndex index="3" value="3"/>
<VarRegionIndex index="4" value="5"/>
</VarData>
</VarStore>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
<!-- RegionCount=3 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
<Region index="1">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="2">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=2 -->
<VarData index="0">
<!-- ItemCount=1 -->
<NumShorts value="0"/>
<!-- VarRegionCount=0 -->
<Item index="0" value="[]"/>
</VarData>
<VarData index="1">
<!-- ItemCount=1 -->
<NumShorts value="3"/>
<!-- VarRegionCount=3 -->
<VarRegionIndex index="0" value="0"/>
<VarRegionIndex index="1" value="1"/>
<VarRegionIndex index="2" value="2"/>
<Item index="0" value="[794, 344, -244]"/>
</VarData>
</VarStore>
<AdvWidthMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="A" outer="1" inner="0"/>
</AdvWidthMap>
</HVAR>
<MVAR>
<Version value="0x00010000"/>
<Reserved value="0"/>
<ValueRecordSize value="8"/>
<!-- ValueRecordCount=3 -->
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=2 -->
<!-- RegionCount=3 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
</Region>
<Region index="1">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="0.0"/>
<EndCoord value="0.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
<Region index="2">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
<VarRegionAxis index="1">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=2 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="1"/>
<Item index="0" value="[-100]"/>
<Item index="1" value="[100]"/>
</VarData>
</VarStore>
<ValueRecord index="0">
<ValueTag value="cpht"/>
<VarIdx value="1"/>
</ValueRecord>
<ValueRecord index="1">
<ValueTag value="hasc"/>
<VarIdx value="1"/>
</ValueRecord>
<ValueRecord index="2">
<ValueTag value="hlgp"/>
<VarIdx value="0"/>
</ValueRecord>
</MVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=2 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wdth"/>
<AxisNameID value="258"/> <!-- width -->
<AxisOrdering value="0"/>
</Axis>
<Axis index="1">
<AxisTag value="wght"/>
<AxisNameID value="259"/> <!-- weight -->
<AxisOrdering value="1"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
<fvar>
<!-- Width -->
<Axis>
<AxisTag>wdth</AxisTag>
<Flags>0x0</Flags>
<MinValue>0.0</MinValue>
<DefaultValue>0.0</DefaultValue>
<MaxValue>1000.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>100.0</MinValue>
<DefaultValue>100.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<AxisNameID>257</AxisNameID>
</Axis>
</fvar>
</ttFont>

View File

@ -0,0 +1,648 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="uni6868"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.004"/>
<checkSumAdjustment value="0x7377173c"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Apr 29 17:39:47 2021"/>
<modified value="Thu Apr 29 08:51:43 2021"/>
<xMin value="46"/>
<yMin value="-72"/>
<xMax value="960"/>
<yMax value="833"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1160"/>
<descent value="-288"/>
<lineGap value="0"/>
<advanceWidthMax value="1000"/>
<minLeftSideBearing value="46"/>
<minRightSideBearing value="40"/>
<xMaxExtent value="960"/>
<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="1"/>
</hhea>
<maxp>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="3"/>
<xAvgCharWidth value="989"/>
<usWeightClass value="100"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
<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="325"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="11"/>
<bWeight value="2"/>
<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 00000000"/>
<ulUnicodeRange2 value="00001000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="ADBO"/>
<fsSelection value="00000000 00000000"/>
<usFirstCharIndex value="26728"/>
<usLastCharIndex value="26728"/>
<sTypoAscender value="880"/>
<sTypoDescender value="-120"/>
<sTypoLineGap value="0"/>
<usWinAscent value="1160"/>
<usWinDescent value="288"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="543"/>
<sCapHeight value="733"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="6"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="1000" lsb="100"/>
<mtx name="uni6868" width="1000" lsb="46"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x6868" name="uni6868"/><!-- CJK UNIFIED IDEOGRAPH-6868 -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x6868" name="uni6868"/><!-- CJK UNIFIED IDEOGRAPH-6868 -->
</cmap_format_4>
</cmap>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
© 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
2.004;ADBO;NotoSansSC-Thin;ADOBE
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.004;hotconv 1.0.118;makeotfexe 2.5.65603
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="260" platformID="3" platEncID="1" langID="0x409">
DemiLight
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="262" platformID="3" platEncID="1" langID="0x409">
Medium
</namerecord>
<namerecord nameID="263" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="264" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
<namerecord nameID="265" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
<namerecord nameID="266" platformID="3" platEncID="1" langID="0x409">
Thin
</namerecord>
<namerecord nameID="267" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="268" platformID="3" platEncID="1" langID="0x409">
Light
</namerecord>
<namerecord nameID="269" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Light
</namerecord>
<namerecord nameID="270" platformID="3" platEncID="1" langID="0x409">
DemiLight
</namerecord>
<namerecord nameID="271" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-DemiLight
</namerecord>
<namerecord nameID="272" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="273" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Regular
</namerecord>
<namerecord nameID="274" platformID="3" platEncID="1" langID="0x409">
Medium
</namerecord>
<namerecord nameID="275" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Medium
</namerecord>
<namerecord nameID="276" platformID="3" platEncID="1" langID="0x409">
Bold
</namerecord>
<namerecord nameID="277" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Bold
</namerecord>
<namerecord nameID="278" platformID="3" platEncID="1" langID="0x409">
Black
</namerecord>
<namerecord nameID="279" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Black
</namerecord>
</name>
<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-125"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDSelect format="0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
<FontDict index="1">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef" fdSelectIndex="0">
</CharString>
<CharString name="uni6868" fdSelectIndex="1">
69 271 -16 33 2 blend
rmoveto
-30 856 30 -95 40 95 3 blend
vlineto
-443 103 -81 -61 2 blend
rmoveto
-446 30 446 5 119 -5 3 blend
vlineto
-62 -110 -125 -2 2 blend
rmoveto
-87 -119 -170 -109 -147 -49 7 -5 9 -11 5 -9 145 54 174 111 90 124 11 40 23 37 5 14 24 -25 35 -45 16 -26 1 -4 -29 -15 1 -12 18 blend
rrcurveto
71 12 39 33 2 blend
rmoveto
-27 -13 -86 -39 2 blend
rlineto
88 -127 173 -108 158 -50 5 9 9 10 7 6 -159 45 -170 104 -84 124 7 22 -25 14 -16 1 16 28 35 46 25 23 19 -10 19 -35 6 -50 18 blend
rrcurveto
-451 501 -120 18 2 blend
rmoveto
42 -51 44 -70 16 -45 -11 5 -10 8 -3 5 6 blend
rrcurveto
28 15 -17 44 -44 68 -42 50 86 50 3 -4 6 -9 9 -8 8 blend
rlinecurve
183 56 -86 -8 2 blend
rmoveto
-472 28 472 -50 111 50 3 blend
vlineto
-273 -379 -84 31 2 blend
rmoveto
16 -26 70 33 93 45 88 42 42 -101 -2 8 -13 5 -16 7 8 blend
rlinecurve
-7 26 -97 -46 -98 -46 -65 -32 87 9 -3 7 -3 5 7 blend
-28 rlinecurve
467 173 19 -103 2 blend
rmoveto
59 -44 67 -64 31 -43 -24 2 -24 5 -14 5 6 blend
rrcurveto
26 17 -33 43 -67 63 -58 43 84 51 13 -5 22 -8 22 -4 8 blend
rlinecurve
8 104 -63 31 2 blend
rmoveto
-29 340 29 -90 -29 90 3 blend
vlineto
-291 89 -3 -2 2 blend
rmoveto
-33 -81 -82 -84 -90 -50 7 -5 9 -11 4 -6 94 52 84 89 38 88 -6 12 -3 4 6 4 18 -19 29 -37 16 -23 3 6 14 7 25 9 18 blend
rrcurveto
251 -81 -122 39 2 blend
rmoveto
-7 -14 1 blend
vlineto
-76 -215 -200 -89 -239 -37 6 -7 8 -12 4 -7 243 43 202 90 84 231 17 41 27 6 11 5 19 -20 30 -48 10 -27 -1 4 -4 21 -1 1 18 blend
rrcurveto
-17 12 -7 -2 -71 33 -17 -2 4 blend
rlineto
</CharString>
</CharStrings>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=0 -->
<NumShorts value="0"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
</VarData>
</VarStore>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=0 -->
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=2 -->
<NumShorts value="0"/>
<!-- VarRegionCount=0 -->
<Item index="0" value="[]"/>
<Item index="1" value="[]"/>
</VarData>
</VarStore>
</HVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="265"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=7 -->
<AxisValueArray>
<AxisValue index="0" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="258"/> <!-- Thin -->
<NominalValue value="100.0"/>
<RangeMinValue value="100.0"/>
<RangeMaxValue value="199.0"/>
</AxisValue>
<AxisValue index="1" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="259"/> <!-- Light -->
<NominalValue value="300.0"/>
<RangeMinValue value="200.0"/>
<RangeMaxValue value="349.0"/>
</AxisValue>
<AxisValue index="2" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="260"/> <!-- DemiLight -->
<NominalValue value="350.0"/>
<RangeMinValue value="350.0"/>
<RangeMaxValue value="399.0"/>
</AxisValue>
<AxisValue index="3" Format="2">
<AxisIndex value="0"/>
<Flags value="2"/> <!-- ElidableAxisValueName -->
<ValueNameID value="261"/> <!-- Regular -->
<NominalValue value="400.0"/>
<RangeMinValue value="400.0"/>
<RangeMaxValue value="499.0"/>
</AxisValue>
<AxisValue index="4" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="262"/> <!-- Medium -->
<NominalValue value="500.0"/>
<RangeMinValue value="500.0"/>
<RangeMaxValue value="650.0"/>
</AxisValue>
<AxisValue index="5" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="263"/> <!-- Bold -->
<NominalValue value="700.0"/>
<RangeMinValue value="650.0"/>
<RangeMaxValue value="800.0"/>
</AxisValue>
<AxisValue index="6" Format="2">
<AxisIndex value="0"/>
<Flags value="0"/>
<ValueNameID value="264"/> <!-- Black -->
<NominalValue value="900.0"/>
<RangeMinValue value="800.0"/>
<RangeMaxValue value="900.0"/>
</AxisValue>
</AxisValueArray>
<ElidedFallbackNameID value="256"/> <!-- Regular -->
</STAT>
<VORG>
<majorVersion value="1"/>
<minorVersion value="0"/>
<defaultVertOriginY value="880"/>
<numVertOriginYMetrics value="0"/>
</VORG>
<VVAR>
<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>
<AdvHeightMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="uni6868" outer="0" inner="0"/>
</AdvHeightMap>
<VOrgMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="uni6868" outer="0" inner="0"/>
</VOrgMap>
</VVAR>
<avar>
<version major="1" minor="0"/>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<mapping from="0.0" to="0.0"/>
<mapping from="0.25" to="0.16"/>
<mapping from="0.3125" to="0.32"/>
<mapping from="0.375" to="0.39"/>
<mapping from="0.5" to="0.56"/>
<mapping from="0.75" to="0.78"/>
<mapping from="1.0" to="1.0"/>
</segment>
</avar>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>100.0</MinValue>
<DefaultValue>100.0</DefaultValue>
<MaxValue>900.0</MaxValue>
<AxisNameID>265</AxisNameID>
</Axis>
<!-- Thin -->
<!-- PostScript: NotoSansSC-Thin -->
<NamedInstance flags="0x0" postscriptNameID="267" subfamilyNameID="266">
<coord axis="wght" value="100.0"/>
</NamedInstance>
<!-- Light -->
<!-- PostScript: NotoSansSC-Light -->
<NamedInstance flags="0x0" postscriptNameID="269" subfamilyNameID="268">
<coord axis="wght" value="300.0"/>
</NamedInstance>
<!-- DemiLight -->
<!-- PostScript: NotoSansSC-DemiLight -->
<NamedInstance flags="0x0" postscriptNameID="271" subfamilyNameID="270">
<coord axis="wght" value="350.0"/>
</NamedInstance>
<!-- Regular -->
<!-- PostScript: NotoSansSC-Regular -->
<NamedInstance flags="0x0" postscriptNameID="273" subfamilyNameID="272">
<coord axis="wght" value="400.0"/>
</NamedInstance>
<!-- Medium -->
<!-- PostScript: NotoSansSC-Medium -->
<NamedInstance flags="0x0" postscriptNameID="275" subfamilyNameID="274">
<coord axis="wght" value="500.0"/>
</NamedInstance>
<!-- Bold -->
<!-- PostScript: NotoSansSC-Bold -->
<NamedInstance flags="0x0" postscriptNameID="277" subfamilyNameID="276">
<coord axis="wght" value="700.0"/>
</NamedInstance>
<!-- Black -->
<!-- PostScript: NotoSansSC-Black -->
<NamedInstance flags="0x0" postscriptNameID="279" subfamilyNameID="278">
<coord axis="wght" value="900.0"/>
</NamedInstance>
</fvar>
<vhea>
<tableVersion value="0x00011000"/>
<ascent value="500"/>
<descent value="-500"/>
<lineGap value="0"/>
<advanceHeightMax value="1000"/>
<minTopSideBearing value="47"/>
<minBottomSideBearing value="48"/>
<yMaxExtent value="952"/>
<caretSlopeRise value="0"/>
<caretSlopeRun value="1"/>
<caretOffset value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<reserved4 value="0"/>
<metricDataFormat value="0"/>
<numberOfVMetrics value="1"/>
</vhea>
<vmtx>
<mtx name=".notdef" height="1000" tsb="0"/>
<mtx name="uni6868" height="1000" tsb="47"/>
</vmtx>
</ttFont>

View File

@ -0,0 +1,476 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="hyphen"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.004"/>
<checkSumAdjustment value="0xe123fa9"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Apr 29 17:39:47 2021"/>
<modified value="Tue May 14 20:02:30 2024"/>
<xMin value="46"/>
<yMin value="245"/>
<xMax value="302"/>
<yMax value="315"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1160"/>
<descent value="-288"/>
<lineGap value="0"/>
<advanceWidthMax value="1000"/>
<minLeftSideBearing value="44"/>
<minRightSideBearing value="47"/>
<xMaxExtent value="300"/>
<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>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="3"/>
<xAvgCharWidth value="674"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
<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="325"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="11"/>
<bWeight value="2"/>
<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="ADBO"/>
<fsSelection value="00000000 00000000"/>
<usFirstCharIndex value="45"/>
<usLastCharIndex value="45"/>
<sTypoAscender value="880"/>
<sTypoDescender value="-120"/>
<sTypoLineGap value="0"/>
<usWinAscent value="1160"/>
<usWinDescent value="288"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="543"/>
<sCapHeight value="733"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="6"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="1000" lsb="100"/>
<mtx name="hyphen" width="347" lsb="44"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x2d" name="hyphen"/><!-- HYPHEN-MINUS -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x2d" name="hyphen"/><!-- HYPHEN-MINUS -->
</cmap_format_4>
</cmap>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
© 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
2.004;ADBO;NotoSansSC-Thin;ADOBE
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.004;hotconv 1.0.118;makeotfexe 2.5.65603
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="265" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-125"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDSelect format="0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
<FontDict index="1">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef" fdSelectIndex="0">
</CharString>
<CharString name="hyphen" fdSelectIndex="1">
46 245 rmoveto
256 70 -256 hlineto
</CharString>
</CharStrings>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="0"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="1"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="2"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="3"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="4"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="5"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=6 -->
<FeatureRecord index="0">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="1">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="2">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="3">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="4">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
<FeatureRecord index="5">
<FeatureTag value="kern"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
</FeatureList>
<LookupList>
<!-- LookupCount=1 -->
<Lookup index="0">
<LookupType value="2"/>
<LookupFlag value="0"/>
<!-- SubTableCount=1 -->
<PairPos index="0" Format="2">
<Coverage>
<Glyph value="hyphen"/>
</Coverage>
<ValueFormat1 value="68"/>
<ValueFormat2 value="0"/>
<ClassDef1>
</ClassDef1>
<ClassDef2>
<ClassDef glyph="hyphen" class="1"/>
</ClassDef2>
<!-- Class1Count=1 -->
<!-- Class2Count=2 -->
<Class1Record index="0">
<Class2Record index="0">
<Value1 XAdvance="0"/>
</Class2Record>
<Class2Record index="1">
<Value1 XAdvance="0"/>
</Class2Record>
</Class1Record>
</PairPos>
</Lookup>
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="265"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=1 -->
<AxisValueArray>
<AxisValue index="0" Format="2">
<AxisIndex value="0"/>
<Flags value="2"/> <!-- ElidableAxisValueName -->
<ValueNameID value="261"/> <!-- Regular -->
<NominalValue value="400.0"/>
<RangeMinValue value="400.0"/>
<RangeMaxValue value="499.0"/>
</AxisValue>
</AxisValueArray>
<ElidedFallbackNameID value="256"/> <!-- Regular -->
</STAT>
<VORG>
<majorVersion value="1"/>
<minorVersion value="0"/>
<defaultVertOriginY value="880"/>
<numVertOriginYMetrics value="0"/>
</VORG>
<vhea>
<tableVersion value="0x00011000"/>
<ascent value="500"/>
<descent value="-500"/>
<lineGap value="0"/>
<advanceHeightMax value="1000"/>
<minTopSideBearing value="589"/>
<minBottomSideBearing value="341"/>
<yMaxExtent value="659"/>
<caretSlopeRise value="0"/>
<caretSlopeRun value="1"/>
<caretOffset value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<reserved4 value="0"/>
<metricDataFormat value="0"/>
<numberOfVMetrics value="1"/>
</vhea>
<vmtx>
<mtx name=".notdef" height="1000" tsb="0"/>
<mtx name="hyphen" height="1000" tsb="589"/>
</vmtx>
</ttFont>

View File

@ -0,0 +1,350 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<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="1.002"/>
<checkSumAdjustment value="0x1f33d291"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Sep 15 20:38:06 2022"/>
<modified value="Tue May 14 19:31:24 2024"/>
<xMin value="9"/>
<yMin value="0"/>
<xMax value="509"/>
<yMax value="738"/>
<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="525"/>
<minLeftSideBearing value="20"/>
<minRightSideBearing value="5"/>
<xMaxExtent value="520"/>
<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>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="4"/>
<xAvgCharWidth value="513"/>
<usWeightClass value="400"/>
<usWidthClass value="1"/>
<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="LTTR"/>
<fsSelection value="00000000 01000000"/>
<usFirstCharIndex value="65"/>
<usLastCharIndex value="65"/>
<sTypoAscender value="738"/>
<sTypoDescender value="-200"/>
<sTypoLineGap value="263"/>
<usWinAscent value="1000"/>
<usWinDescent value="200"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="500"/>
<sCapHeight value="738"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="2"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="500" lsb="50"/>
<mtx name="A" width="525" lsb="20"/>
</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>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
License same as MutatorMath. BSD 3-clause. [test-token: C]
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
1.002;LTTR;MutatorMathTest-LightCondensed
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
MutatorMathTest LightCondensed
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.002
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
MutatorMathTest-LightCondensed
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Width
</namerecord>
<namerecord nameID="258" platformID="3" platEncID="1" langID="0x409">
width
</namerecord>
<namerecord nameID="259" platformID="3" platEncID="1" langID="0x409">
weight
</namerecord>
</name>
<post>
<formatType value="3.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"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<LanguageGroup value="0"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef">
</CharString>
<CharString name="A">
9 30 1 blend
hmoveto
122 31 1 blend
hlineto
119 738 312 0 2 blend
rlineto
-108 -23 1 blend
hlineto
-54 -590 -205 38 2 blend
rmoveto
332 101 -332 379 0 -379 3 blend
hlineto
266 -249 482 -37 2 blend
rmoveto
155 54 1 blend
hlineto
-134 738 -318 0 2 blend
rlineto
-144 -54 1 blend
hlineto
-44 -122 17 2 2 blend
rmoveto
131 122 -131 58 -2 -58 3 blend
hlineto
</CharString>
</CharStrings>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=0 -->
<NumShorts value="1"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
</VarData>
</VarStore>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=1 -->
<Region index="0">
<VarRegionAxis index="0">
<StartCoord value="0.0"/>
<PeakCoord value="1.0"/>
<EndCoord value="1.0"/>
</VarRegionAxis>
</Region>
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=2 -->
<NumShorts value="1"/>
<!-- VarRegionCount=1 -->
<VarRegionIndex index="0" value="0"/>
<Item index="0" value="[0]"/>
<Item index="1" value="[703]"/>
</VarData>
</VarStore>
<AdvWidthMap>
<Map glyph=".notdef" outer="0" inner="0"/>
<Map glyph="A" outer="0" inner="1"/>
</AdvWidthMap>
</HVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=2 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wdth"/>
<AxisNameID value="258"/> <!-- width -->
<AxisOrdering value="0"/>
</Axis>
<Axis index="1">
<AxisTag value="wght"/>
<AxisNameID value="259"/> <!-- weight -->
<AxisOrdering value="1"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
<fvar>
<!-- Width -->
<Axis>
<AxisTag>wdth</AxisTag>
<Flags>0x0</Flags>
<MinValue>0.0</MinValue>
<DefaultValue>0.0</DefaultValue>
<MaxValue>1000.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
</fvar>
</ttFont>

View File

@ -0,0 +1,377 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="4.51">
<GlyphOrder>
<!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
<GlyphID id="0" name=".notdef"/>
<GlyphID id="1" name="uni6868"/>
</GlyphOrder>
<head>
<!-- Most of this table will be recalculated by the compiler -->
<tableVersion value="1.0"/>
<fontRevision value="2.004"/>
<checkSumAdjustment value="0x25b28144"/>
<magicNumber value="0x5f0f3cf5"/>
<flags value="00000000 00000011"/>
<unitsPerEm value="1000"/>
<created value="Thu Apr 29 17:39:47 2021"/>
<modified value="Tue May 14 19:41:58 2024"/>
<xMin value="36"/>
<yMin value="-81"/>
<xMax value="966"/>
<yMax value="841"/>
<macStyle value="00000000 00000000"/>
<lowestRecPPEM value="3"/>
<fontDirectionHint value="2"/>
<indexToLocFormat value="0"/>
<glyphDataFormat value="0"/>
</head>
<hhea>
<tableVersion value="0x00010000"/>
<ascent value="1160"/>
<descent value="-288"/>
<lineGap value="0"/>
<advanceWidthMax value="1000"/>
<minLeftSideBearing value="46"/>
<minRightSideBearing value="24"/>
<xMaxExtent value="976"/>
<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="1"/>
</hhea>
<maxp>
<tableVersion value="0x5000"/>
<numGlyphs value="2"/>
</maxp>
<OS_2>
<!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
will be recalculated by the compiler -->
<version value="3"/>
<xAvgCharWidth value="1000"/>
<usWeightClass value="400"/>
<usWidthClass value="5"/>
<fsType value="00000000 00000000"/>
<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="325"/>
<sFamilyClass value="0"/>
<panose>
<bFamilyType value="2"/>
<bSerifStyle value="11"/>
<bWeight value="2"/>
<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 00000000"/>
<ulUnicodeRange2 value="00001000 00000000 00000000 00000000"/>
<ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
<ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
<achVendID value="ADBO"/>
<fsSelection value="00000000 00000000"/>
<usFirstCharIndex value="26728"/>
<usLastCharIndex value="26728"/>
<sTypoAscender value="880"/>
<sTypoDescender value="-120"/>
<sTypoLineGap value="0"/>
<usWinAscent value="1160"/>
<usWinDescent value="288"/>
<ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
<ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
<sxHeight value="543"/>
<sCapHeight value="733"/>
<usDefaultChar value="0"/>
<usBreakChar value="32"/>
<usMaxContext value="6"/>
</OS_2>
<hmtx>
<mtx name=".notdef" width="1000" lsb="100"/>
<mtx name="uni6868" width="1000" lsb="46"/>
</hmtx>
<cmap>
<tableVersion version="0"/>
<cmap_format_4 platformID="0" platEncID="3" language="0">
<map code="0x6868" name="uni6868"/><!-- CJK UNIFIED IDEOGRAPH-6868 -->
</cmap_format_4>
<cmap_format_4 platformID="3" platEncID="1" language="0">
<map code="0x6868" name="uni6868"/><!-- CJK UNIFIED IDEOGRAPH-6868 -->
</cmap_format_4>
</cmap>
<name>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
© 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
2.004;ADBO;NotoSansSC-Thin;ADOBE
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Noto Sans SC
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.004;hotconv 1.0.118;makeotfexe 2.5.65603
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
NotoSansSC-Thin
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="261" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="265" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
<post>
<formatType value="3.0"/>
<italicAngle value="0.0"/>
<underlinePosition value="-125"/>
<underlineThickness value="50"/>
<isFixedPitch value="0"/>
<minMemType42 value="0"/>
<maxMemType42 value="0"/>
<minMemType1 value="0"/>
<maxMemType1 value="0"/>
</post>
<CFF2>
<major value="2"/>
<minor value="0"/>
<CFFFont name="CFF2Font">
<FontMatrix value="0.001 0 0 0.001 0 0"/>
<FDSelect format="0"/>
<FDArray>
<FontDict index="0">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
<FontDict index="1">
<Private>
<BlueValues value="-250 -250 1100 1100"/>
<BlueScale value="0.039625"/>
<BlueShift value="7"/>
<BlueFuzz value="1"/>
<StdHW value="35"/>
<StdVW value="28"/>
<StemSnapV value="28 46"/>
<LanguageGroup value="1"/>
<ExpansionFactor value="0.06"/>
</Private>
</FontDict>
</FDArray>
<CharStrings>
<CharString name=".notdef" fdSelectIndex="0">
</CharString>
<CharString name="uni6868" fdSelectIndex="1">
63 284 rmoveto
-67 872 67 vlineto
-475 79 rmoveto
-444 76 444 vlineto
-111 -111 rmoveto
-83 -103 -161 -95 -145 -44 16 -15 23 -29 11 -19 145 52 163 105 90 119 rrcurveto
86 25 rmoveto
-61 -28 rlineto
91 -118 163 -103 152 -50 11 20 23 28 17 15 -152 41 -163 90 -82 104 rrcurveto
-498 508 rmoveto
38 -49 40 -67 15 -43 rrcurveto
62 35 -16 42 -42 64 -38 47 rlinecurve
149 53 rmoveto
-492 71 492 vlineto
-306 -367 rmoveto
32 -65 69 36 88 47 82 45 rlinecurve
-19 60 -93 -47 -95 -47 -63 -28 rlinecurve
474 133 rmoveto
50 -43 58 -62 26 -41 rrcurveto
59 37 -28 41 -58 60 -49 41 rlinecurve
-17 116 rmoveto
-64 329 64 vlineto
-292 88 rmoveto
-35 -76 -83 -82 -88 -48 14 -12 20 -25 10 -15 95 54 89 92 48 92 rrcurveto
203 -66 rmoveto
-12 vlineto
-69 -199 -189 -87 -235 -35 13 -15 20 -31 8 -18 243 45 200 98 84 231 rrcurveto
-45 25 -14 -3 rlineto
</CharString>
</CharStrings>
</CFFFont>
<GlobalSubrs>
<!-- The 'index' attribute is only for humans; it is ignored when parsed. -->
</GlobalSubrs>
</CFF2>
<GPOS>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GPOS>
<GSUB>
<Version value="0x00010000"/>
<ScriptList>
<!-- ScriptCount=6 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=0 -->
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="1">
<ScriptTag value="cyrl"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="2">
<ScriptTag value="grek"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="3">
<ScriptTag value="hani"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="4">
<ScriptTag value="kana"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
<ScriptRecord index="5">
<ScriptTag value="latn"/>
<Script>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=0 -->
</FeatureList>
<LookupList>
<!-- LookupCount=0 -->
</LookupList>
</GSUB>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="265"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=1 -->
<AxisValueArray>
<AxisValue index="0" Format="2">
<AxisIndex value="0"/>
<Flags value="2"/> <!-- ElidableAxisValueName -->
<ValueNameID value="261"/> <!-- Regular -->
<NominalValue value="400.0"/>
<RangeMinValue value="400.0"/>
<RangeMaxValue value="499.0"/>
</AxisValue>
</AxisValueArray>
<ElidedFallbackNameID value="256"/> <!-- Regular -->
</STAT>
<VORG>
<majorVersion value="1"/>
<minorVersion value="0"/>
<defaultVertOriginY value="880"/>
<numVertOriginYMetrics value="0"/>
</VORG>
<vhea>
<tableVersion value="0x00011000"/>
<ascent value="500"/>
<descent value="-500"/>
<lineGap value="0"/>
<advanceHeightMax value="1000"/>
<minTopSideBearing value="47"/>
<minBottomSideBearing value="31"/>
<yMaxExtent value="969"/>
<caretSlopeRise value="0"/>
<caretSlopeRun value="1"/>
<caretOffset value="0"/>
<reserved1 value="0"/>
<reserved2 value="0"/>
<reserved3 value="0"/>
<reserved4 value="0"/>
<metricDataFormat value="0"/>
<numberOfVMetrics value="1"/>
</vhea>
<vmtx>
<mtx name=".notdef" height="1000" tsb="0"/>
<mtx name="uni6868" height="1000" tsb="47"/>
</vmtx>
</ttFont>

View File

@ -63,6 +63,88 @@ def _get_coordinates(varfont, glyphname):
) )
class InstantiateCFF2Test(object):
@pytest.mark.parametrize(
"location, expected",
[
(
{},
[
44,
256,
6,
-29,
2,
"blend",
"rmoveto",
239,
35,
-239,
44,
90,
-44,
3,
"blend",
"hlineto",
],
),
({"wght": 0}, [44, 256, "rmoveto", 239, 35, -239, "hlineto"]),
({"wght": 0.5}, [47, 242, "rmoveto", 261, 80, -261, "hlineto"]),
({"wght": 1}, [50, 227, "rmoveto", 283, 125, -283, "hlineto"]),
],
)
def test_pin_and_drop_axis(self, varfont, location, expected):
varfont = ttLib.TTFont()
varfont.importXML(os.path.join(TESTDATA, "CFF2Instancer-VF-1.ttx"))
location = instancer.NormalizedAxisLimits(location)
instancer.instantiateCFF2(varfont, location)
instancer.instantiateHVAR(varfont, location)
program = varfont["CFF2"].cff.topDictIndex[0].CharStrings.values()[1].program
assert program == expected
@pytest.mark.parametrize(
"source_ttx, expected_ttx",
[
("CFF2Instancer-VF-1.ttx", "CFF2Instancer-VF-1-instance-400.ttx"),
("CFF2Instancer-VF-2.ttx", "CFF2Instancer-VF-2-instance-400.ttx"),
("CFF2Instancer-VF-3.ttx", "CFF2Instancer-VF-3-instance-400.ttx"),
],
)
def test_full_instance(self, varfont, source_ttx, expected_ttx):
varfont = ttLib.TTFont()
varfont.importXML(os.path.join(TESTDATA, source_ttx))
s = BytesIO()
varfont.save(s)
s.seek(0)
varfont = ttLib.TTFont(s)
instance = instancer.instantiateVariableFont(varfont, {"wght": 400})
s = BytesIO()
instance.save(s)
s.seek(0)
instance = ttLib.TTFont(s)
s = StringIO()
instance.saveXML(s)
actual = stripVariableItemsFromTTX(s.getvalue())
expected = ttLib.TTFont()
expected.importXML(os.path.join(TESTDATA, "test_results", expected_ttx))
s = BytesIO()
expected.save(s)
s.seek(0)
expected = ttLib.TTFont(s)
s = StringIO()
expected.saveXML(s)
expected = stripVariableItemsFromTTX(s.getvalue())
assert actual == expected
class InstantiateGvarTest(object): class InstantiateGvarTest(object):
@pytest.mark.parametrize("glyph_name", ["hyphen"]) @pytest.mark.parametrize("glyph_name", ["hyphen"])
@pytest.mark.parametrize( @pytest.mark.parametrize(