Merge pull request #1752 from anthrotype/region-axis-count
enforce VarStore RegionAxisCount == fvar.AxisCount
This commit is contained in:
commit
5790f7f9af
@ -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,8 +692,16 @@ 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.
|
||||
ref = writer.writeCountReference(table, conv.name, conv.staticSize)
|
||||
table[conv.name] = None
|
||||
# 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:
|
||||
writer[conv.name] = ref
|
||||
elif conv.isLookupType:
|
||||
|
@ -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):
|
||||
|
@ -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'])
|
||||
|
13
Tests/varLib/data/SingleMaster.designspace
Normal file
13
Tests/varLib/data/SingleMaster.designspace
Normal 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>
|
98
Tests/varLib/data/test_results/SingleMaster.ttx
Normal file
98
Tests/varLib/data/test_results/SingleMaster.ttx
Normal 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>
|
@ -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.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user