Merge remote-tracking branch 'origin/main' into variable-colr

This commit is contained in:
Cosimo Lupo 2022-06-24 10:16:51 +01:00
commit fcd2a67f52
11 changed files with 56 additions and 23 deletions

View File

@ -9,6 +9,9 @@ on:
tags:
- '*.*.*' # e.g. 1.0.0 or 20.15.10
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest

View File

@ -6,6 +6,9 @@ on:
pull_request:
branches: [main]
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest

View File

@ -764,7 +764,7 @@ class Builder(object):
gdef.Version = 0x00010002 if gdef.MarkGlyphSetsDef else 0x00010000
if self.varstorebuilder:
store = self.varstorebuilder.finish()
if store.VarData:
if store:
gdef.Version = 0x00010003
gdef.VarStore = store
varidx_map = store.optimize()

View File

@ -73,6 +73,7 @@ class Parser(object):
self.next_token_location_ = None
lexerClass = IncludingLexer if followIncludes else NonIncludingLexer
self.lexer_ = lexerClass(featurefile, includeDir=includeDir)
self.missing = {}
self.advance_lexer_(comments=True)
def parse(self):
@ -125,6 +126,16 @@ class Parser(object):
),
self.cur_token_location_,
)
# Report any missing glyphs at the end of parsing
if self.missing:
error = [
" %s (first found at %s)" % (name, loc)
for name, loc in self.missing.items()
]
raise FeatureLibError(
"The following glyph names are referenced but are missing from the "
"glyph set:\n" + ("\n".join(error)), None
)
return self.doc_
def parse_anchor_(self):
@ -2073,19 +2084,18 @@ class Parser(object):
raise FeatureLibError("Expected a glyph name or CID", self.cur_token_location_)
def check_glyph_name_in_glyph_set(self, *names):
"""Raises if glyph name (just `start`) or glyph names of a
range (`start` and `end`) are not in the glyph set.
"""Adds a glyph name (just `start`) or glyph names of a
range (`start` and `end`) which are not in the glyph set
to the "missing list" for future error reporting.
If no glyph set is present, does nothing.
"""
if self.glyphNames_:
missing = [name for name in names if name not in self.glyphNames_]
if missing:
raise FeatureLibError(
"The following glyph names are referenced but are missing from the "
f"glyph set: {', '.join(missing)}",
self.cur_token_location_,
)
for name in names:
if name in self.glyphNames_:
continue
if name not in self.missing:
self.missing[name] = self.cur_token_location_
def expect_markClass_reference_(self):
name = self.expect_class_name_()

View File

@ -534,7 +534,9 @@ class OTTableWriter(object):
https://github.com/harfbuzz/uharfbuzz/blob/main/src/uharfbuzz/_harfbuzz.pyx#L1149
"""
internedTables = {}
self._doneWriting(internedTables, shareExtension=True)
# TODO: Restore shareExtension=True after we fix
# https://github.com/fonttools/fonttools/issues/2661
self._doneWriting(internedTables, shareExtension=False)
tables = []
obj_list = []
done = {}

View File

@ -488,7 +488,7 @@ def _get_advance_metrics(font, masterModel, master_ttfs,
vOrigMap[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound)
indirectStore = storeBuilder.finish()
mapping2 = indirectStore.optimize()
mapping2 = indirectStore.optimize(use_NO_VARIATION_INDEX=False)
advMapping = [mapping2[advMapping[g]] for g in glyphOrder]
advanceMapping = builder.buildVarIdxMap(advMapping, glyphOrder)
@ -608,7 +608,7 @@ def _add_BASE(font, masterModel, master_ttfs, axisTags):
merger.mergeTables(font, master_ttfs, ['BASE'])
store = merger.store_builder.finish()
if not store.VarData:
if not store:
return
base = font['BASE'].table
assert base.Version == 0x00010000
@ -623,7 +623,7 @@ def _merge_OTL(font, model, master_fonts, axisTags):
merger.mergeTables(font, master_fonts, ['GSUB', 'GDEF', 'GPOS'])
store = merger.store_builder.finish()
if not store.VarData:
if not store:
return
try:
GDEF = font['GDEF'].table

View File

@ -633,6 +633,7 @@ def instantiateItemVariationStore(itemVarStore, fvarAxes, axisLimits):
for major, deltas in enumerate(defaultDeltaArray)
for minor, delta in enumerate(deltas)
}
defaultDeltas[itemVarStore.NO_VARIATION_INDEX] = 0
return defaultDeltas

View File

@ -7,6 +7,10 @@ from functools import partial
from collections import defaultdict
NO_VARIATION_INDEX = 0xFFFFFFFF
ot.VarStore.NO_VARIATION_INDEX = NO_VARIATION_INDEX
def _getLocationKey(loc):
return tuple(sorted(loc.items(), key=lambda kv: kv[0]))
@ -135,6 +139,11 @@ def VarRegion_get_support(self, fvar_axes):
ot.VarRegion.get_support = VarRegion_get_support
def VarStore___bool__(self):
return bool(self.VarData)
ot.VarStore.__bool__ = VarStore___bool__
class VarStoreInstancer(object):
def __init__(self, varstore, fvar_axes, location={}):
@ -169,6 +178,7 @@ class VarStoreInstancer(object):
def __getitem__(self, varidx):
major, minor = varidx >> 16, varidx & 0xFFFF
if varidx == NO_VARIATION_INDEX: return 0.
varData = self._varData
scalars = [self._getScalar(ri) for ri in varData[major].VarRegionIndex]
deltas = varData[major].Item[minor]
@ -431,7 +441,7 @@ class _EncodingDict(dict):
return chars
def VarStore_optimize(self):
def VarStore_optimize(self, use_NO_VARIATION_INDEX=True):
"""Optimize storage. Returns mapping from old VarIdxes to new ones."""
# TODO
@ -455,6 +465,10 @@ def VarStore_optimize(self):
row[regionIdx] += v
row = tuple(row)
if use_NO_VARIATION_INDEX and not any(row):
front_mapping[(major<<16)+minor] = None
continue
encodings.add_row(row)
front_mapping[(major<<16)+minor] = row
@ -537,9 +551,9 @@ def VarStore_optimize(self):
back_mapping[item] = (major<<16)+minor
# Compile final mapping.
varidx_map = {}
varidx_map = {NO_VARIATION_INDEX:NO_VARIATION_INDEX}
for k,v in front_mapping.items():
varidx_map[k] = back_mapping[v]
varidx_map[k] = back_mapping[v] if v is not None else NO_VARIATION_INDEX
# Remove unused regions.
self.prune_regions()

View File

@ -316,7 +316,7 @@ class ParserTest(unittest.TestCase):
def test_strict_glyph_name_check(self):
self.parse("@bad = [a b ccc];", glyphNames=("a", "b", "ccc"))
with self.assertRaisesRegex(FeatureLibError, "missing from the glyph set: ccc"):
with self.assertRaisesRegex(FeatureLibError, "(?s)missing from the glyph set:.*ccc"):
self.parse("@bad = [a b ccc];", glyphNames=("a", "b"))
def test_glyphclass(self):

View File

@ -360,7 +360,7 @@ class InstantiateHVARTest(object):
assert support == pytest.approx(expectedRegion[axisTag])
assert len(varStore.VarData) == 1
assert varStore.VarData[0].ItemCount == 2
assert varStore.VarData[0].ItemCount == 1
assert hvar.AdvWidthMap is not None
advWithMap = hvar.AdvWidthMap.mapping
@ -368,9 +368,7 @@ class InstantiateHVARTest(object):
assert advWithMap[".notdef"] == advWithMap["space"]
varIdx = advWithMap[".notdef"]
# these glyphs have no metrics variations in the test font
assert varStore.VarData[varIdx >> 16].Item[varIdx & 0xFFFF] == (
[0] * varStore.VarData[0].VarRegionCount
)
assert varIdx == varStore.NO_VARIATION_INDEX
varIdx = advWithMap["hyphen"]
assert varStore.VarData[varIdx >> 16].Item[varIdx & 0xFFFF] == expectedDeltas
@ -458,6 +456,8 @@ class InstantiateItemVariationStoreTest(object):
defaultDeltaArray = []
for varidx, delta in sorted(defaultDeltas.items()):
if varidx == varStore.NO_VARIATION_INDEX:
continue
major, minor = varidx >> 16, varidx & 0xFFFF
if major == len(defaultDeltaArray):
defaultDeltaArray.append([])

View File

@ -13,7 +13,7 @@ from fontTools.ttLib.tables.otTables import VarStore
(
[{}, {"a": 1}],
[
[10, 20],
[10, 10], # Test NO_VARIATION_INDEX
[100, 2000],
[100, 22000],
],