Merge remote-tracking branch 'origin/master' into partial-instancer

This commit is contained in:
Cosimo Lupo 2019-07-31 15:22:48 +01:00
commit 5455517689
No known key found for this signature in database
GPG Key ID: 20D4A261E4A0E642
15 changed files with 976 additions and 881 deletions

View File

@ -5,6 +5,6 @@ from fontTools.misc.loggingTools import configLogger
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
version = __version__ = "3.43.2.dev0" version = __version__ = "3.43.3.dev0"
__all__ = ["version", "log", "configLogger"] __all__ = ["version", "log", "configLogger"]

View File

@ -31,6 +31,7 @@ Here is how to build a minimal TTF:
from fontTools.fontBuilder import FontBuilder from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.pens.ttGlyphPen import TTGlyphPen
def drawTestGlyph(pen): def drawTestGlyph(pen):
pen.moveTo((100, 100)) pen.moveTo((100, 100))
pen.lineTo((100, 1000)) pen.lineTo((100, 1000))
@ -38,35 +39,39 @@ def drawTestGlyph(pen):
pen.lineTo((500, 100)) pen.lineTo((500, 100))
pen.closePath() pen.closePath()
fb = FontBuilder(1024, isTTF=True)
fb.setupGlyphOrder([".notdef", ".null", "A", "a"])
fb.setupCharacterMap({65: "A", 97: "a"})
advanceWidths = {".notdef": 600, "A": 600, "a": 600, ".null": 600} fb = FontBuilder(1024, isTTF=True)
fb.setupGlyphOrder([".notdef", ".null", "space", "A", "a"])
fb.setupCharacterMap({32: "space", 65: "A", 97: "a"})
advanceWidths = {".notdef": 600, "space": 500, "A": 600, "a": 600, ".null": 0}
familyName = "HelloTestFont" familyName = "HelloTestFont"
styleName = "TotallyNormal" styleName = "TotallyNormal"
nameStrings = dict(familyName=dict(en="HelloTestFont", nl="HalloTestFont"), version = "0.1"
styleName=dict(en="TotallyNormal", nl="TotaalNormaal"))
nameStrings['psName'] = familyName + "-" + styleName nameStrings = dict(
familyName=dict(en=familyName, nl="HalloTestFont"),
styleName=dict(en=styleName, nl="TotaalNormaal"),
uniqueFontIdentifier="fontBuilder: " + familyName + "." + styleName,
fullName=familyName + "-" + styleName,
psName=familyName + "-" + styleName,
version="Version " + version,
)
pen = TTGlyphPen(None) pen = TTGlyphPen(None)
drawTestGlyph(pen) drawTestGlyph(pen)
glyph = pen.glyph() glyph = pen.glyph()
glyphs = {".notdef": glyph, "A": glyph, "a": glyph, ".null": glyph} glyphs = {".notdef": glyph, "space": glyph, "A": glyph, "a": glyph, ".null": glyph}
fb.setupGlyf(glyphs) fb.setupGlyf(glyphs)
metrics = {} metrics = {}
glyphTable = fb.font["glyf"] glyphTable = fb.font["glyf"]
for gn, advanceWidth in advanceWidths.items(): for gn, advanceWidth in advanceWidths.items():
metrics[gn] = (advanceWidth, glyphTable[gn].xMin) metrics[gn] = (advanceWidth, glyphTable[gn].xMin)
fb.setupHorizontalMetrics(metrics) fb.setupHorizontalMetrics(metrics)
fb.setupHorizontalHeader(ascent=824, descent=-200)
fb.setupHorizontalHeader(ascent=824, descent=200)
fb.setupNameTable(nameStrings) fb.setupNameTable(nameStrings)
fb.setupOS2() fb.setupOS2(sTypoAscender=824, usWinAscent=824, usWinDescent=200)
fb.setupPost() fb.setupPost()
fb.save("test.ttf") fb.save("test.ttf")
``` ```
@ -76,6 +81,7 @@ And here's how to build a minimal OTF:
from fontTools.fontBuilder import FontBuilder from fontTools.fontBuilder import FontBuilder
from fontTools.pens.t2CharStringPen import T2CharStringPen from fontTools.pens.t2CharStringPen import T2CharStringPen
def drawTestGlyph(pen): def drawTestGlyph(pen):
pen.moveTo((100, 100)) pen.moveTo((100, 100))
pen.lineTo((100, 1000)) pen.lineTo((100, 1000))
@ -83,35 +89,45 @@ def drawTestGlyph(pen):
pen.lineTo((500, 100)) pen.lineTo((500, 100))
pen.closePath() pen.closePath()
fb = FontBuilder(1024, isTTF=False)
fb.setupGlyphOrder([".notdef", ".null", "A", "a"])
fb.setupCharacterMap({65: "A", 97: "a"})
advanceWidths = {".notdef": 600, "A": 600, "a": 600, ".null": 600} fb = FontBuilder(1024, isTTF=False)
fb.setupGlyphOrder([".notdef", ".null", "space", "A", "a"])
fb.setupCharacterMap({32: "space", 65: "A", 97: "a"})
advanceWidths = {".notdef": 600, "space": 500, "A": 600, "a": 600, ".null": 0}
familyName = "HelloTestFont" familyName = "HelloTestFont"
styleName = "TotallyNormal" styleName = "TotallyNormal"
nameStrings = dict(familyName=dict(en="HelloTestFont", nl="HalloTestFont"), version = "0.1"
styleName=dict(en="TotallyNormal", nl="TotaalNormaal"))
nameStrings['psName'] = familyName + "-" + styleName nameStrings = dict(
familyName=dict(en=familyName, nl="HalloTestFont"),
styleName=dict(en=styleName, nl="TotaalNormaal"),
uniqueFontIdentifier="fontBuilder: " + familyName + "." + styleName,
fullName=familyName + "-" + styleName,
psName=familyName + "-" + styleName,
version="Version " + version,
)
pen = T2CharStringPen(600, None) pen = T2CharStringPen(600, None)
drawTestGlyph(pen) drawTestGlyph(pen)
charString = pen.getCharString() charString = pen.getCharString()
charStrings = {".notdef": charString, "A": charString, "a": charString, ".null": charString} charStrings = {
fb.setupCFF(nameStrings['psName'], {"FullName": nameStrings['psName']}, charStrings, {}) ".notdef": charString,
"space": charString,
"A": charString,
"a": charString,
".null": charString,
}
fb.setupCFF(nameStrings["psName"], {"FullName": nameStrings["psName"]}, charStrings, {})
lsb = {gn: cs.calcBounds(None)[0] for gn, cs in charStrings.items()} lsb = {gn: cs.calcBounds(None)[0] for gn, cs in charStrings.items()}
metrics = {} metrics = {}
for gn, advanceWidth in advanceWidths.items(): for gn, advanceWidth in advanceWidths.items():
metrics[gn] = (advanceWidth, lsb[gn]) metrics[gn] = (advanceWidth, lsb[gn])
fb.setupHorizontalMetrics(metrics) fb.setupHorizontalMetrics(metrics)
fb.setupHorizontalHeader(ascent=824, descent=200) fb.setupHorizontalHeader(ascent=824, descent=200)
fb.setupNameTable(nameStrings) fb.setupNameTable(nameStrings)
fb.setupOS2() fb.setupOS2(sTypoAscender=824, usWinAscent=824, usWinDescent=200)
fb.setupPost() fb.setupPost()
fb.save("test.otf") fb.save("test.otf")
``` ```
""" """

View File

@ -1391,7 +1391,7 @@ class UFOWriter(UFOReader):
def _getGlyphSetFormatVersion1(self, validateRead, validateWrite, glyphNameToFileNameFunc=None): def _getGlyphSetFormatVersion1(self, validateRead, validateWrite, glyphNameToFileNameFunc=None):
from fontTools.ufoLib.glifLib import GlyphSet from fontTools.ufoLib.glifLib import GlyphSet
glyphSubFS = self.fs.makedir(DEFAULT_GLYPHS_DIRNAME, recreate=True), glyphSubFS = self.fs.makedir(DEFAULT_GLYPHS_DIRNAME, recreate=True)
return GlyphSet( return GlyphSet(
glyphSubFS, glyphSubFS,
glyphNameToFileNameFunc=glyphNameToFileNameFunc, glyphNameToFileNameFunc=glyphNameToFileNameFunc,

View File

@ -23,8 +23,7 @@ from __future__ import unicode_literals
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.misc.fixedTools import otRound from fontTools.misc.fixedTools import otRound
from fontTools.misc.arrayTools import Vector from fontTools.misc.arrayTools import Vector
from fontTools.ttLib import TTFont, newTable, TTLibError from fontTools.ttLib import TTFont, newTable
from fontTools.ttLib.tables._n_a_m_e import NameRecord
from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance
from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
from fontTools.ttLib.tables.ttProgram import Program from fontTools.ttLib.tables.ttProgram import Program
@ -36,7 +35,7 @@ from fontTools.varLib.merger import VariationMerger
from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib.mvar import MVAR_ENTRIES
from fontTools.varLib.iup import iup_delta_optimize from fontTools.varLib.iup import iup_delta_optimize
from fontTools.varLib.featureVars import addFeatureVariations from fontTools.varLib.featureVars import addFeatureVariations
from fontTools.designspaceLib import DesignSpaceDocument, AxisDescriptor from fontTools.designspaceLib import DesignSpaceDocument
from collections import OrderedDict, namedtuple from collections import OrderedDict, namedtuple
import os.path import os.path
import logging import logging
@ -1017,9 +1016,6 @@ def main(args=None):
designspace_filename = options.designspace designspace_filename = options.designspace
finder = MasterFinder(options.master_finder) finder = MasterFinder(options.master_finder)
outfile = options.outfile
if outfile is None:
outfile = os.path.splitext(designspace_filename)[0] + '-VF.ttf'
vf, _, _ = build( vf, _, _ = build(
designspace_filename, designspace_filename,
@ -1028,6 +1024,11 @@ def main(args=None):
optimize=options.optimize optimize=options.optimize
) )
outfile = options.outfile
if outfile is None:
ext = "otf" if vf.sfntVersion == "OTTO" else "ttf"
outfile = os.path.splitext(designspace_filename)[0] + '-VF.' + ext
log.info("Saving variation font %s", outfile) log.info("Saving variation font %s", outfile)
vf.save(outfile) vf.save(outfile)

25
Lib/fontTools/varLib/cff.py Executable file → Normal file
View File

@ -131,7 +131,7 @@ class MergeDictError(TypeError):
def conv_to_int(num): def conv_to_int(num):
if num % 1 == 0: if isinstance(num, float) and num.is_integer():
return int(num) return int(num)
return num return num
@ -198,17 +198,17 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
pds.append(pd) pds.append(pd)
num_masters = len(pds) num_masters = len(pds)
for key, value in private_dict.rawDict.items(): for key, value in private_dict.rawDict.items():
dataList = []
if key not in pd_blend_fields: if key not in pd_blend_fields:
continue continue
if isinstance(value, list): if isinstance(value, list):
try: try:
values = [pd.rawDict[key] for pd in pds] values = [pd.rawDict[key] for pd in pds]
except KeyError: except KeyError:
del private_dict.rawDict[key]
print( print(
b"Warning: {key} in default font Private dict is " "Warning: {key} in default font Private dict is "
b"missing from another font, and was " "missing from another font, and was "
b"discarded.".format(key=key)) "discarded.".format(key=key))
continue continue
try: try:
values = zip(*values) values = zip(*values)
@ -227,7 +227,6 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
and is converted finally to: and is converted finally to:
OtherBlues = [[-217, 17.0, 46.0], [-205, 0.0, 0.0]] OtherBlues = [[-217, 17.0, 46.0], [-205, 0.0, 0.0]]
""" """
dataList = []
prev_val_list = [0] * num_masters prev_val_list = [0] * num_masters
any_points_differ = False any_points_differ = False
for val_list in values: for val_list in values:
@ -237,8 +236,6 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
any_points_differ = True any_points_differ = True
prev_val_list = val_list prev_val_list = val_list
deltas = sub_model.getDeltas(rel_list) deltas = sub_model.getDeltas(rel_list)
# Convert numbers with no decimal part to an int.
deltas = [conv_to_int(delta) for delta in deltas]
# For PrivateDict BlueValues, the default font # For PrivateDict BlueValues, the default font
# values are absolute, not relative to the prior value. # values are absolute, not relative to the prior value.
deltas[0] = val_list[0] deltas[0] = val_list[0]
@ -253,6 +250,18 @@ def merge_PrivateDicts(top_dicts, vsindex_dict, var_model, fd_map):
dataList = sub_model.getDeltas(values) dataList = sub_model.getDeltas(values)
else: else:
dataList = values[0] dataList = values[0]
# Convert numbers with no decimal part to an int
if isinstance(dataList, list):
for i, item in enumerate(dataList):
if isinstance(item, list):
for j, jtem in enumerate(item):
dataList[i][j] = conv_to_int(jtem)
else:
dataList[i] = conv_to_int(item)
else:
dataList = conv_to_int(dataList)
private_dict.rawDict[key] = dataList private_dict.rawDict[key] = dataList

View File

@ -71,7 +71,7 @@ def overlayFeatureVariations(conditionalSubstitutions):
and rules with the same Box merged. The more specific rules appear earlier and rules with the same Box merged. The more specific rules appear earlier
in the resulting list. Moreover, instead of just a dictionary of substitutions, in the resulting list. Moreover, instead of just a dictionary of substitutions,
a list of dictionaries is returned for substitutions corresponding to each a list of dictionaries is returned for substitutions corresponding to each
uniq space, with each dictionary being identical to one of the input unique space, with each dictionary being identical to one of the input
substitution dictionaries. These dictionaries are not merged to allow data substitution dictionaries. These dictionaries are not merged to allow data
sharing when they are converted into font tables. sharing when they are converted into font tables.
@ -79,6 +79,7 @@ def overlayFeatureVariations(conditionalSubstitutions):
>>> condSubst = [ >>> condSubst = [
... # A list of (Region, Substitution) tuples. ... # A list of (Region, Substitution) tuples.
... ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}), ... ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
... ([{"wght": (0.5, 1.0)}], {"dollar": "dollar.rvrn"}),
... ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}), ... ([{"wdth": (0.5, 1.0)}], {"cent": "cent.rvrn"}),
... ] ... ]
>>> from pprint import pprint >>> from pprint import pprint
@ -107,7 +108,8 @@ def overlayFeatureVariations(conditionalSubstitutions):
# rules for the same region. # rules for the same region.
merged = OrderedDict() merged = OrderedDict()
for key,value in reversed(conditionalSubstitutions): for key,value in reversed(conditionalSubstitutions):
key = tuple(sorted(hashdict(cleanupBox(k)) for k in key)) key = tuple(sorted((hashdict(cleanupBox(k)) for k in key),
key=lambda d: tuple(sorted(d.items()))))
if key in merged: if key in merged:
merged[key].update(value) merged[key].update(value)
else: else:

View File

@ -1,3 +1,9 @@
3.43.2 (released 2019-07-10)
----------------------------
- [featureVars] Fixed region-merging code on python3 (#1659).
- [varLib.cff] Fixed merging of sparse PrivateDict items (#1653).
3.43.1 (released 2019-06-19) 3.43.1 (released 2019-06-19)
---------------------------- ----------------------------

File diff suppressed because it is too large Load Diff

View File

@ -374,6 +374,7 @@
<FontName value="MasterSet_Kanji-w0.00-Generic"/> <FontName value="MasterSet_Kanji-w0.00-Generic"/>
<Private> <Private>
<BlueValues value="-250 -250 1100 1100"/> <BlueValues value="-250 -250 1100 1100"/>
<FamilyBlues value="-250 -240 1100 1110"/>
<BlueScale value="0.039625"/> <BlueScale value="0.039625"/>
<BlueShift value="7"/> <BlueShift value="7"/>
<BlueFuzz value="0"/> <BlueFuzz value="0"/>

View File

@ -86,10 +86,10 @@
<BlueShift value="7"/> <BlueShift value="7"/>
<BlueFuzz value="0"/> <BlueFuzz value="0"/>
<StdHW> <StdHW>
<blend value="67 -39.0 67.0"/> <blend value="67 -39 67"/>
</StdHW> </StdHW>
<StdVW> <StdVW>
<blend value="85 -51.0 87.0"/> <blend value="85 -51 87"/>
</StdVW> </StdVW>
</Private> </Private>
</FontDict> </FontDict>

View File

@ -31,10 +31,10 @@
<BlueShift value="7"/> <BlueShift value="7"/>
<BlueFuzz value="0"/> <BlueFuzz value="0"/>
<StdHW> <StdHW>
<blend value="28 39.0"/> <blend value="28 39"/>
</StdHW> </StdHW>
<StdVW> <StdVW>
<blend value="34 51.0"/> <blend value="34 51"/>
</StdVW> </StdVW>
</Private> </Private>
</FontDict> </FontDict>

View File

@ -132,6 +132,7 @@
<FontDict index="0"> <FontDict index="0">
<Private> <Private>
<BlueValues value="-250 -250 1100 1100"/> <BlueValues value="-250 -250 1100 1100"/>
<FamilyBlues value="-250 -240 1100 1110"/>
<BlueScale value="0.039625"/> <BlueScale value="0.039625"/>
<BlueShift value="7"/> <BlueShift value="7"/>
<BlueFuzz value="0"/> <BlueFuzz value="0"/>

View File

@ -9,3 +9,7 @@ munkres==1.0.12; platform_python_implementation == "PyPy" and python_version < '
munkres==1.1.2; platform_python_implementation == "PyPy" and python_version >= '3.5' munkres==1.1.2; platform_python_implementation == "PyPy" and python_version >= '3.5'
zopfli==0.1.6 zopfli==0.1.6
fs==2.4.8 fs==2.4.8
# lxml 4.4.0 breaks OrderedDict attributes in python < 3.6 so we pin to previous version
# https://bugs.launchpad.net/lxml/+bug/1838252
lxml==4.3.5; python_version < '3.6' # pyup: ignore
lxml==4.4.0; python_version >= '3.6'

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 3.43.2.dev0 current_version = 3.43.3.dev0
commit = True commit = True
tag = False tag = False
tag_name = {new_version} tag_name = {new_version}

View File

@ -352,7 +352,7 @@ def find_data_files(manpath="share/man"):
setup( setup(
name="fonttools", name="fonttools",
version="3.43.2.dev0", version="3.43.3.dev0",
description="Tools to manipulate font files", description="Tools to manipulate font files",
author="Just van Rossum", author="Just van Rossum",
author_email="just@letterror.com", author_email="just@letterror.com",