[otBase|otTables] enforce VarStore RegionAxisCount == fvar.AxisCount

even when there are no Regions and thus we can't take the length of VarRegionAxis array.
This is to appease older versions of OTS which blindly enforce this rule and
reject a VF that has, e.g., an empty HVAR table with no regions if the
HVAR.VarStore.VarRegionList.RegionAxisCount != fvar.AxisCount.

Fixes https://github.com/fonttools/fonttools/issues/1670

Related:
https://github.com/fonttools/fonttools/pull/1671
https://github.com/googlefonts/fontmake/issues/565
https://github.com/khaledhosny/ots/pull/192
This commit is contained in:
Cosimo Lupo 2019-10-24 12:51:48 +01:00
parent d96c92f95e
commit adc5b2997e
No known key found for this signature in database
GPG Key ID: 20D4A261E4A0E642
2 changed files with 28 additions and 3 deletions

View File

@ -498,6 +498,11 @@ class OTTableWriter(object):
return OverflowErrorRecord( (self.tableTag, LookupListIndex, SubTableIndex, itemName, itemIndex) )
class LiteralCount(int):
"""A count value that should be taken literally, rather than recomputed on compile."""
pass
class CountReference(object):
"""A reference to a Count value, not a count of references."""
def __init__(self, table, name, size=None, value=None):
@ -690,8 +695,12 @@ 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
if not isinstance(value, LiteralCount):
# we ignore the current count value since it's being recomputed,
# unless this is a LiteralCount, which is assumed to be already correct.
value = None
ref = writer.writeCountReference(table, conv.name, conv.staticSize, value)
table[conv.name] = value
if conv.isPropagated:
writer[conv.name] = ref
elif conv.isLookupType:

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, LiteralCount
import logging
import struct
@ -687,6 +687,22 @@ 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 = LiteralCount(len(fvarTable.axes))
return self.__dict__.copy()
class SingleSubst(FormatSwitchingBaseTable):
def populateDefaults(self, propagator=None):