Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def empty_varfont(designspace_path):
designspace = fontTools.designspaceLib.DesignSpaceDocument.fromfile(
designspace_path
)
for source in designspace.sources:
source.font = testutil.empty_UFO(source.styleName)
ufo2ft.compileInterpolatableTTFsFromDS(designspace, inplace=True)
varfont, _, _ = fontTools.varLib.build(designspace)
return varfont
def generate_variable_font(
designspace_path: Path,
stylespace_path: Path,
additional_locations: Optional[Mapping[str, float]] = None,
) -> fontTools.ttLib.TTFont:
designspace = fontTools.designspaceLib.DesignSpaceDocument.fromfile(
designspace_path
)
for source in designspace.sources:
source.font = empty_UFO(source.styleName)
ufo2ft.compileInterpolatableTTFsFromDS(designspace, inplace=True)
varfont, _, _ = fontTools.varLib.build(designspace)
stylespace = statmake.classes.Stylespace.from_file(stylespace_path)
if additional_locations is None:
additional_locations = designspace.lib.get(
"org.statmake.additionalLocations", {}
)
statmake.lib.apply_stylespace_to_variable_font(
stylespace, varfont, additional_locations
)
return reload_font(varfont)
# panose
data = getAttrWithFallback(font.info, "openTypeOS2Panose")
panose = Panose()
panose.bFamilyType = data[0]
panose.bSerifStyle = data[1]
panose.bWeight = data[2]
panose.bProportion = data[3]
panose.bContrast = data[4]
panose.bStrokeVariation = data[5]
panose.bArmStyle = data[6]
panose.bLetterForm = data[7]
panose.bMidline = data[8]
panose.bXHeight = data[9]
os2.panose = panose
# Unicode ranges
uniRanges = getAttrWithFallback(font.info, "openTypeOS2UnicodeRanges")
os2.ulUnicodeRange1 = intListToNum(uniRanges, 0, 32)
os2.ulUnicodeRange2 = intListToNum(uniRanges, 32, 32)
os2.ulUnicodeRange3 = intListToNum(uniRanges, 64, 32)
os2.ulUnicodeRange4 = intListToNum(uniRanges, 96, 32)
# codepage ranges
codepageRanges = getAttrWithFallback(font.info, "openTypeOS2CodePageRanges")
os2.ulCodePageRange1 = intListToNum(codepageRanges, 0, 32)
os2.ulCodePageRange2 = intListToNum(codepageRanges, 32, 32)
# vendor id
os2.achVendID = tounicode(
getAttrWithFallback(font.info, "openTypeOS2VendorID"),
encoding="ascii", errors="ignore")
# vertical metrics
os2.sxHeight = round(getAttrWithFallback(font.info, "xHeight"))
os2.sCapHeight = round(getAttrWithFallback(font.info, "capHeight"))
os2.sTypoAscender = round(getAttrWithFallback(font.info, "openTypeOS2TypoAscender"))
height, top = vmtx[glyphName]
heights.append(height)
bounds = self.glyphBoundingBoxes[glyphName]
if bounds is None:
continue
bottom = height - top - (bounds.yMax - bounds.yMin)
tops.append(top)
bottoms.append(bottom)
vhea.advanceHeightMax = max(heights)
vhea.minTopSideBearing = max(tops)
vhea.minBottomSideBearing = max(bottoms)
vhea.yMaxExtent = vhea.minTopSideBearing - (head.yMax - head.yMin)
# misc
vhea.caretSlopeRise = getAttrWithFallback(font.info, "openTypeVheaCaretSlopeRise")
vhea.caretSlopeRun = getAttrWithFallback(font.info, "openTypeVheaCaretSlopeRun")
vhea.caretOffset = getAttrWithFallback(font.info, "openTypeVheaCaretOffset")
vhea.reserved0 = 0
vhea.reserved1 = 0
vhea.reserved2 = 0
vhea.reserved3 = 0
vhea.reserved4 = 0
vhea.metricDataFormat = 0
# glyph count
vhea.numberOfVMetrics = len(self.allGlyphs)
font = self.ufo
os2.version = 0x0004
# average glyph width
widths = [glyph.width for glyph in self.allGlyphs.values() if glyph.width > 0]
os2.xAvgCharWidth = round(sum(widths) / len(widths))
# weight and width classes
os2.usWeightClass = getAttrWithFallback(font.info, "openTypeOS2WeightClass")
os2.usWidthClass = getAttrWithFallback(font.info, "openTypeOS2WidthClass")
# embedding
os2.fsType = intListToNum(getAttrWithFallback(font.info, "openTypeOS2Type"), 0, 16)
# subscript, superscript, strikeout values, taken from AFDKO:
# FDK/Tools/Programs/makeotf/makeotf_lib/source/hotconv/hot.c
unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")
italicAngle = getAttrWithFallback(font.info, "italicAngle")
xHeight = getAttrWithFallback(font.info, "xHeight")
def adjustOffset(offset, angle):
"""Adjust Y offset based on italic angle, to get X offset."""
return offset * math.tan(math.radians(-angle)) if angle else 0
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXSize")
if v is None:
v = unitsPerEm * 0.65
os2.ySubscriptXSize = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYSize")
if v is None:
v = unitsPerEm * 0.6
os2.ySubscriptYSize = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYOffset")
if v is None:
v = unitsPerEm * 0.075
os2.ySubscriptYOffset = round(v)
os2.fsType = intListToNum(getAttrWithFallback(font.info, "openTypeOS2Type"), 0, 16)
# subscript, superscript, strikeout values, taken from AFDKO:
# FDK/Tools/Programs/makeotf/makeotf_lib/source/hotconv/hot.c
unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")
italicAngle = getAttrWithFallback(font.info, "italicAngle")
xHeight = getAttrWithFallback(font.info, "xHeight")
def adjustOffset(offset, angle):
"""Adjust Y offset based on italic angle, to get X offset."""
return offset * math.tan(math.radians(-angle)) if angle else 0
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXSize")
if v is None:
v = unitsPerEm * 0.65
os2.ySubscriptXSize = _roundInt(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYSize")
if v is None:
v = unitsPerEm * 0.6
os2.ySubscriptYSize = _roundInt(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYOffset")
if v is None:
v = unitsPerEm * 0.075
os2.ySubscriptYOffset = _roundInt(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXOffset")
if v is None:
v = adjustOffset(-os2.ySubscriptYOffset, italicAngle)
os2.ySubscriptXOffset = _roundInt(v)
v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXSize")
if v is None:
v = os2.ySubscriptXSize
os2.ySuperscriptXSize = _roundInt(v)
**This should not be called externally.** Subclasses
may override or supplement this method to handle the
table creation in a different way if desired.
"""
self.otf["head"] = head = newTable("head")
font = self.ufo
head.checkSumAdjustment = 0
head.tableVersion = 1.0
head.magicNumber = 0x5F0F3CF5
# version numbers
# limit minor version to 3 digits as recommended in OpenType spec:
# https://www.microsoft.com/typography/otspec/recom.htm
versionMajor = getAttrWithFallback(font.info, "versionMajor")
versionMinor = getAttrWithFallback(font.info, "versionMinor")
fullFontRevision = float("%d.%03d" % (versionMajor, versionMinor))
head.fontRevision = round(fullFontRevision, 3)
if head.fontRevision != fullFontRevision:
logger.warning(
"Minor version in %s has too many digits and won't fit into "
"the head table's fontRevision field; rounded to %s.",
fullFontRevision, head.fontRevision)
# upm
head.unitsPerEm = getAttrWithFallback(font.info, "unitsPerEm")
# times
head.created = dateStringToTimeValue(getAttrWithFallback(font.info, "openTypeHeadCreated")) - mac_epoch_diff
head.modified = dateStringToTimeValue(dateStringForNow()) - mac_epoch_diff
# bounding box
v = unitsPerEm * 0.6
os2.ySubscriptYSize = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptYOffset")
if v is None:
v = unitsPerEm * 0.075
os2.ySubscriptYOffset = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SubscriptXOffset")
if v is None:
v = adjustOffset(-os2.ySubscriptYOffset, italicAngle)
os2.ySubscriptXOffset = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXSize")
if v is None:
v = os2.ySubscriptXSize
os2.ySuperscriptXSize = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYSize")
if v is None:
v = os2.ySubscriptYSize
os2.ySuperscriptYSize = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptYOffset")
if v is None:
v = unitsPerEm * 0.35
os2.ySuperscriptYOffset = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2SuperscriptXOffset")
if v is None:
v = adjustOffset(os2.ySuperscriptYOffset, italicAngle)
os2.ySuperscriptXOffset = round(v)
v = getAttrWithFallback(font.info, "openTypeOS2StrikeoutSize")
if v is None:
v = getAttrWithFallback(font.info, "postscriptUnderlineThickness")
os2.yStrikeoutSize = round(v)
2: styleName,
3: getAttrWithFallback(font.info, "openTypeNameUniqueID"),
4: fullName,
5: getAttrWithFallback(font.info, "openTypeNameVersion"),
6: getAttrWithFallback(font.info, "postscriptFontName"),
7: getAttrWithFallback(font.info, "trademark"),
8: getAttrWithFallback(font.info, "openTypeNameManufacturer"),
9: getAttrWithFallback(font.info, "openTypeNameDesigner"),
10: getAttrWithFallback(font.info, "openTypeNameDescription"),
11: getAttrWithFallback(font.info, "openTypeNameManufacturerURL"),
12: getAttrWithFallback(font.info, "openTypeNameDesignerURL"),
13: getAttrWithFallback(font.info, "openTypeNameLicense"),
14: getAttrWithFallback(font.info, "openTypeNameLicenseURL"),
16: getAttrWithFallback(
font.info, "openTypeNamePreferredFamilyName"),
17: getAttrWithFallback(
font.info, "openTypeNamePreferredSubfamilyName"),
}
# don't add typographic names if they are the same as the legacy ones
if nameVals[1] == nameVals[16]:
del nameVals[16]
if nameVals[2] == nameVals[17]:
del nameVals[17]
# postscript font name
if nameVals[6]:
nameVals[6] = normalizeStringForPostscript(nameVals[6])
for nameId in sorted(nameVals.keys()):
nameVal = nameVals[nameId]
if not nameVal:
continue
panose.bProportion = data[3]
panose.bContrast = data[4]
panose.bStrokeVariation = data[5]
panose.bArmStyle = data[6]
panose.bLetterForm = data[7]
panose.bMidline = data[8]
panose.bXHeight = data[9]
os2.panose = panose
# Unicode ranges
uniRanges = getAttrWithFallback(font.info, "openTypeOS2UnicodeRanges")
os2.ulUnicodeRange1 = intListToNum(uniRanges, 0, 32)
os2.ulUnicodeRange2 = intListToNum(uniRanges, 32, 32)
os2.ulUnicodeRange3 = intListToNum(uniRanges, 64, 32)
os2.ulUnicodeRange4 = intListToNum(uniRanges, 96, 32)
# codepage ranges
codepageRanges = getAttrWithFallback(font.info, "openTypeOS2CodePageRanges")
os2.ulCodePageRange1 = intListToNum(codepageRanges, 0, 32)
os2.ulCodePageRange2 = intListToNum(codepageRanges, 32, 32)
# vendor id
os2.achVendID = tounicode(
getAttrWithFallback(font.info, "openTypeOS2VendorID"),
encoding="ascii", errors="ignore")
# vertical metrics
os2.sxHeight = _roundInt(getAttrWithFallback(font.info, "xHeight"))
os2.sCapHeight = _roundInt(getAttrWithFallback(font.info, "capHeight"))
os2.sTypoAscender = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoAscender"))
os2.sTypoDescender = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoDescender"))
os2.sTypoLineGap = _roundInt(getAttrWithFallback(font.info, "openTypeOS2TypoLineGap"))
os2.usWinAscent = _roundInt(getAttrWithFallback(font.info, "openTypeOS2WinAscent"))
os2.usWinDescent = _roundInt(getAttrWithFallback(font.info, "openTypeOS2WinDescent"))
# style mapping
selection = list(getAttrWithFallback(font.info, "openTypeOS2Selection"))