Merge pull request #1752 from anthrotype/region-axis-count

enforce VarStore RegionAxisCount == fvar.AxisCount
This commit is contained in:
Cosimo Lupo 2019-10-29 13:02:43 +00:00 committed by GitHub
commit 5790f7f9af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 16 deletions

View File

@ -513,6 +513,8 @@ class CountReference(object):
table[name] = value
else:
assert table[name] == value, (name, table[name], value)
def getValue(self):
return self.table[self.name]
def getCountData(self):
v = self.table[self.name]
if v is None: v = 0
@ -690,6 +692,14 @@ class BaseTable(object):
# table. We will later store it here.
# We add a reference: by the time the data is assembled
# the Count value will be filled in.
# We ignore the current count value since it will be recomputed,
# unless it's a CountReference that was already initialized in a custom preWrite.
if isinstance(value, CountReference):
ref = value
ref.size = conv.staticSize
writer.writeData(ref)
table[conv.name] = ref.getValue()
else:
ref = writer.writeCountReference(table, conv.name, conv.staticSize)
table[conv.name] = None
if conv.isPropagated:

View File

@ -7,7 +7,7 @@ converter objects from otConverters.py.
"""
from fontTools.misc.py23 import *
from fontTools.misc.textTools import pad, safeEval
from .otBase import BaseTable, FormatSwitchingBaseTable, ValueRecord
from .otBase import BaseTable, FormatSwitchingBaseTable, ValueRecord, CountReference
import logging
import struct
@ -687,6 +687,25 @@ class VarIdxMap(BaseTable):
mapping[glyph] = (outer << 16) | inner
class VarRegionList(BaseTable):
def preWrite(self, font):
# The OT spec says VarStore.VarRegionList.RegionAxisCount should always
# be equal to the fvar.axisCount, and OTS < v8.0.0 enforces this rule
# even when the VarRegionList is empty. We can't treat RegionAxisCount
# like a normal propagated count (== len(Region[i].VarRegionAxis)),
# otherwise it would default to 0 if VarRegionList is empty.
# Thus, we force it to always be equal to fvar.axisCount.
# https://github.com/khaledhosny/ots/pull/192
fvarTable = font.get("fvar")
if fvarTable:
self.RegionAxisCount = len(fvarTable.axes)
return {
**self.__dict__,
"RegionAxisCount": CountReference(self.__dict__, "RegionAxisCount")
}
class SingleSubst(FormatSwitchingBaseTable):
def populateDefaults(self, propagator=None):

View File

@ -213,15 +213,13 @@ def _add_gvar(font, masterModel, master_ttfs, tolerance=0.5, optimize=True):
log.info("Generating gvar")
assert "gvar" not in font
gvar = font["gvar"] = newTable('gvar')
gvar.version = 1
gvar.reserved = 0
gvar.variations = {}
glyf = font['glyf']
# use hhea.ascent of base master as default vertical origin when vmtx is missing
baseAscent = font['hhea'].ascent
variations = {}
for glyph in font.getGlyphOrder():
isComposite = glyf[glyph].isComposite()
@ -241,7 +239,6 @@ def _add_gvar(font, masterModel, master_ttfs, tolerance=0.5, optimize=True):
del allControls
# Update gvar
gvar.variations[glyph] = []
deltas = model.getDeltas(allCoords)
supports = model.supports
assert len(deltas) == len(supports)
@ -280,7 +277,14 @@ def _add_gvar(font, masterModel, master_ttfs, tolerance=0.5, optimize=True):
if optimized_len < unoptimized_len:
var = var_opt
gvar.variations[glyph].append(var)
variations.setdefault(glyph, []).append(var)
if variations:
gvar = font["gvar"] = newTable('gvar')
gvar.version = 1
gvar.reserved = 0
gvar.variations = {g: variations.get(g, []) for g in font.getGlyphOrder()}
def _remove_TTHinting(font):
for tag in ("cvar", "cvt ", "fpgm", "prep"):
@ -350,19 +354,21 @@ def _merge_TTHinting(font, masterModel, master_ttfs, tolerance=0.5):
_remove_TTHinting(font)
return
# We can build the cvar table now.
cvar = font["cvar"] = newTable('cvar')
cvar.version = 1
cvar.variations = []
variations = []
deltas, supports = masterModel.getDeltasAndSupports(all_cvs)
for i,(delta,support) in enumerate(zip(deltas[1:], supports[1:])):
delta = [otRound(d) for d in delta]
if all(abs(v) <= tolerance for v in delta):
continue
var = TupleVariation(support, delta)
cvar.variations.append(var)
variations.append(var)
# We can build the cvar table now.
if variations:
cvar = font["cvar"] = newTable('cvar')
cvar.version = 1
cvar.variations = variations
_MetricsFields = namedtuple('_MetricsFields',
['tableTag', 'metricsTag', 'sb1', 'sb2', 'advMapping', 'vOrigMapping'])

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='utf-8'?>
<designspace format="3">
<axes>
<axis default="400" maximum="400" minimum="400" name="weight" tag="wght" />
</axes>
<sources>
<source familyname="Test Family" filename="master_ufo/TestFamily-Master0.ufo" name="master_0">
<location>
<dimension name="weight" xvalue="400" />
</location>
</source>
</sources>
</designspace>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.0">
<GDEF>
<Version value="0x00010003"/>
<GlyphClassDef Format="2">
<ClassDef glyph="uni0024" class="1"/>
<ClassDef glyph="uni0024.nostroke" class="1"/>
<ClassDef glyph="uni0041" class="1"/>
<ClassDef glyph="uni0061" class="1"/>
</GlyphClassDef>
</GDEF>
<HVAR>
<Version value="0x00010000"/>
<VarStore Format="1">
<Format value="1"/>
<VarRegionList>
<!-- RegionAxisCount=1 -->
<!-- RegionCount=0 -->
</VarRegionList>
<!-- VarDataCount=1 -->
<VarData index="0">
<!-- ItemCount=6 -->
<NumShorts value="0"/>
<!-- VarRegionCount=0 -->
<Item index="0" value="[]"/>
<Item index="1" value="[]"/>
<Item index="2" value="[]"/>
<Item index="3" value="[]"/>
<Item index="4" value="[]"/>
<Item index="5" value="[]"/>
</VarData>
</VarStore>
</HVAR>
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=1 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="256"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
<fvar>
<!-- Weight -->
<Axis>
<AxisTag>wght</AxisTag>
<Flags>0x0</Flags>
<MinValue>400.0</MinValue>
<DefaultValue>400.0</DefaultValue>
<MaxValue>400.0</MaxValue>
<AxisNameID>256</AxisNameID>
</Axis>
</fvar>
<name>
<namerecord nameID="256" platformID="1" platEncID="0" langID="0x0" unicode="True">
Weight
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
Version 1.001;ADBO;Test Family Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Test Family
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 1.001
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
TestFamily-Master0
</namerecord>
<namerecord nameID="9" platformID="3" platEncID="1" langID="0x409">
Frank Grießhammer
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
Master 0
</namerecord>
<namerecord nameID="256" platformID="3" platEncID="1" langID="0x409">
Weight
</namerecord>
</name>
</ttFont>

View File

@ -584,6 +584,15 @@ class BuildTest(unittest.TestCase):
self.expect_ttx(varfont, expected_ttx_path, tables)
self.check_ttx_dump(varfont, expected_ttx_path, tables, suffix)
def test_varlib_build_single_master(self):
self._run_varlib_build_test(
designspace_name='SingleMaster',
font_name='TestFamily',
tables=['GDEF', 'HVAR', 'MVAR', 'STAT', 'fvar', 'cvar', 'gvar', 'name'],
expected_ttx_name='SingleMaster',
save_before_dump=True,
)
def test_kerning_merging(self):
"""Test the correct merging of class-based pair kerning.