[varLib] Generate direct HVAR
This commit is contained in:
parent
e2da17e032
commit
c1717224da
@ -89,7 +89,7 @@ class BaseConverter(object):
|
|||||||
self.tableClass = tableClass
|
self.tableClass = tableClass
|
||||||
self.isCount = name.endswith("Count")
|
self.isCount = name.endswith("Count")
|
||||||
self.isLookupType = name.endswith("LookupType")
|
self.isLookupType = name.endswith("LookupType")
|
||||||
self.isPropagated = name in ["ClassCount", "Class2Count", "FeatureTag", "SettingsCount", "AxisCount"]
|
self.isPropagated = name in ["ClassCount", "Class2Count", "FeatureTag", "SettingsCount", "VarTupleCount"]
|
||||||
|
|
||||||
def readArray(self, reader, font, tableDict, count):
|
def readArray(self, reader, font, tableDict, count):
|
||||||
"""Read an array of values from the reader."""
|
"""Read an array of values from the reader."""
|
||||||
@ -230,9 +230,19 @@ class GlyphID(SimpleValue):
|
|||||||
class VarAxisID(SimpleValue):
|
class VarAxisID(SimpleValue):
|
||||||
staticSize = 2
|
staticSize = 2
|
||||||
def read(self, reader, font, tableDict):
|
def read(self, reader, font, tableDict):
|
||||||
return font['fvar'].axes[reader.readUShort()]
|
idx = reader.readUShort()
|
||||||
|
try:
|
||||||
|
return font['fvar'].axes[idx].axisTag
|
||||||
|
except (KeyError, IndexError):
|
||||||
|
return idx
|
||||||
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
||||||
writer.writeUShort(font['fvar'].axes.index(value))
|
if not isinstance(value, int):
|
||||||
|
value = tobytes(value)
|
||||||
|
for i,axis in enumerate(font['fvar'].axes):
|
||||||
|
if axis.axisTag == value:
|
||||||
|
value = i
|
||||||
|
break
|
||||||
|
writer.writeUShort(value)
|
||||||
|
|
||||||
class FloatValue(SimpleValue):
|
class FloatValue(SimpleValue):
|
||||||
def xmlRead(self, attrs, content, font):
|
def xmlRead(self, attrs, content, font):
|
||||||
@ -509,9 +519,11 @@ converterMapping = {
|
|||||||
"GlyphID": GlyphID,
|
"GlyphID": GlyphID,
|
||||||
"DeciPoints": DeciPoints,
|
"DeciPoints": DeciPoints,
|
||||||
"Fixed": Fixed,
|
"Fixed": Fixed,
|
||||||
|
"F2Dot14": F2Dot14,
|
||||||
"struct": Struct,
|
"struct": Struct,
|
||||||
"Offset": Table,
|
"Offset": Table,
|
||||||
"LOffset": LTable,
|
"LOffset": LTable,
|
||||||
"ValueRecord": ValueRecord,
|
"ValueRecord": ValueRecord,
|
||||||
|
"VarAxisID": VarAxisID,
|
||||||
"DeltaValue": DeltaValue,
|
"DeltaValue": DeltaValue,
|
||||||
}
|
}
|
||||||
|
@ -845,7 +845,7 @@ otData = [
|
|||||||
# VariationStore
|
# VariationStore
|
||||||
|
|
||||||
('VarAxis', [
|
('VarAxis', [
|
||||||
('uint16', 'VarAxisID', None, None, ''),
|
('VarAxisID', 'VarAxisID', None, None, ''),
|
||||||
('F2Dot14', 'StartCoord', None, None, ''),
|
('F2Dot14', 'StartCoord', None, None, ''),
|
||||||
('F2Dot14', 'PeakCoord', None, None, ''),
|
('F2Dot14', 'PeakCoord', None, None, ''),
|
||||||
('F2Dot14', 'EndCoord', None, None, ''),
|
('F2Dot14', 'EndCoord', None, None, ''),
|
||||||
@ -862,10 +862,10 @@ otData = [
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
('VarItemByteRecord', [
|
('VarItemByteRecord', [
|
||||||
('int8', 'deltas', 'VarTupleCount', 0, ''),
|
('int8', 'Deltas', 'VarTupleCount', 0, ''),
|
||||||
]),
|
]),
|
||||||
('VarItemShortRecord', [
|
('VarItemShortRecord', [
|
||||||
('int16', 'deltas', 'VarTupleCount', 0, ''),
|
('int16', 'Deltas', 'VarTupleCount', 0, ''),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
('VarDeltasFormat1', [
|
('VarDeltasFormat1', [
|
||||||
|
@ -20,11 +20,12 @@ API *will* change in near future.
|
|||||||
"""
|
"""
|
||||||
from __future__ import print_function, division, absolute_import
|
from __future__ import print_function, division, absolute_import
|
||||||
from fontTools.misc.py23 import *
|
from fontTools.misc.py23 import *
|
||||||
from fontTools.ttLib import TTFont
|
from fontTools.ttLib import TTFont, newTable
|
||||||
from fontTools.ttLib.tables._n_a_m_e import NameRecord
|
from fontTools.ttLib.tables._n_a_m_e import NameRecord
|
||||||
from fontTools.ttLib.tables._f_v_a_r import table__f_v_a_r, 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._g_v_a_r import table__g_v_a_r, GlyphVariation
|
from fontTools.ttLib.tables._g_v_a_r import GlyphVariation
|
||||||
|
from fontTools.ttLib.tables import otTables as ot
|
||||||
from fontTools.varLib import builder
|
from fontTools.varLib import builder
|
||||||
import warnings
|
import warnings
|
||||||
try:
|
try:
|
||||||
@ -317,7 +318,7 @@ def _AddName(font, name):
|
|||||||
# Move to fvar table proper?
|
# Move to fvar table proper?
|
||||||
def _add_fvar(font, axes, instances):
|
def _add_fvar(font, axes, instances):
|
||||||
assert "fvar" not in font
|
assert "fvar" not in font
|
||||||
font['fvar'] = fvar = table__f_v_a_r()
|
font['fvar'] = fvar = newTable('fvar')
|
||||||
|
|
||||||
for tag in sorted(axes.keys()):
|
for tag in sorted(axes.keys()):
|
||||||
axis = Axis()
|
axis = Axis()
|
||||||
@ -430,7 +431,7 @@ def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):
|
|||||||
|
|
||||||
print("Generating gvar")
|
print("Generating gvar")
|
||||||
assert "gvar" not in font
|
assert "gvar" not in font
|
||||||
gvar = font["gvar"] = table__g_v_a_r()
|
gvar = font["gvar"] = newTable('gvar')
|
||||||
gvar.version = 1
|
gvar.version = 1
|
||||||
gvar.reserved = 0
|
gvar.reserved = 0
|
||||||
gvar.variations = {}
|
gvar.variations = {}
|
||||||
@ -440,28 +441,56 @@ def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):
|
|||||||
model_base_idx = model.mapping[base_idx]
|
model_base_idx = model.mapping[base_idx]
|
||||||
assert 0 == model_base_idx
|
assert 0 == model_base_idx
|
||||||
|
|
||||||
|
hAdvanceDeltas = {}
|
||||||
|
|
||||||
for glyph in font.getGlyphOrder():
|
for glyph in font.getGlyphOrder():
|
||||||
|
|
||||||
allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
|
allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
|
||||||
allCoords = [d[0] for d in allData]
|
allCoords = [d[0] for d in allData]
|
||||||
allControls = [d[1] for d in allData]
|
allControls = [d[1] for d in allData]
|
||||||
|
allHAdvance = [m["hmtx"].metrics[glyph][0] for m in master_ttfs]
|
||||||
control = allControls[0]
|
control = allControls[0]
|
||||||
if (any(c != control for c in allControls)):
|
if (any(c != control for c in allControls)):
|
||||||
warnings.warn("glyph %s has incompatible masters; skipping" % glyph)
|
warnings.warn("glyph %s has incompatible masters; skipping" % glyph)
|
||||||
continue
|
continue
|
||||||
del allControls
|
del allControls
|
||||||
|
|
||||||
|
# Update gvar
|
||||||
gvar.variations[glyph] = []
|
gvar.variations[glyph] = []
|
||||||
|
|
||||||
deltas = model.getDeltas(allCoords)
|
deltas = model.getDeltas(allCoords)
|
||||||
supports = model.supports
|
supports = model.supports
|
||||||
assert len(deltas) == len(supports)
|
assert len(deltas) == len(supports)
|
||||||
for i,(delta,support) in enumerate(zip(deltas, supports)):
|
for i,(delta,support) in enumerate(zip(deltas[1:], supports[1:])):
|
||||||
if i == model_base_idx:
|
|
||||||
continue
|
|
||||||
var = GlyphVariation(support, delta)
|
var = GlyphVariation(support, delta)
|
||||||
gvar.variations[glyph].append(var)
|
gvar.variations[glyph].append(var)
|
||||||
|
|
||||||
|
hAdvanceDeltas[glyph] = tuple(model.getDeltas(allHAdvance)[1:])
|
||||||
|
|
||||||
|
# Build HVAR
|
||||||
|
|
||||||
|
# We only support the direct mapping right now.
|
||||||
|
|
||||||
|
supports = model.supports[1:]
|
||||||
|
varTupleList = builder.buildVarTupleList(supports)
|
||||||
|
varTupleIndexes = list(range(len(supports)))
|
||||||
|
n = len(supports)
|
||||||
|
items = []
|
||||||
|
zeroes = [0]*n
|
||||||
|
for glyphName in font.getGlyphOrder():
|
||||||
|
items.append(hAdvanceDeltas.get(glyphName, zeroes))
|
||||||
|
while items and items[-1] is zeroes:
|
||||||
|
del items[-1]
|
||||||
|
varDeltas = builder.buildVarDeltas(varTupleIndexes, items)
|
||||||
|
varStore = builder.buildVarStore(varTupleList, [varDeltas])
|
||||||
|
|
||||||
|
assert "HVAR" not in font
|
||||||
|
HVAR = font["HVAR"] = newTable('HVAR')
|
||||||
|
hvar = HVAR.table = ot.HVAR()
|
||||||
|
hvar.Version = 1.0
|
||||||
|
hvar.VarIdxMap = None
|
||||||
|
hvar.VarStore = varStore
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -28,22 +28,23 @@ def buildVarTupleList(supports):
|
|||||||
|
|
||||||
def buildVarDeltas(varTupleIndexes, items):
|
def buildVarDeltas(varTupleIndexes, items):
|
||||||
self = ot.VarDeltas()
|
self = ot.VarDeltas()
|
||||||
self.format = 1 if all(all(128 <= delta <= 127 for delta in item) for item in items) else 2
|
self.Format = 1 if all(all(128 <= delta <= 127 for delta in item) for item in items) else 2
|
||||||
self.VarTupleIndex = list(varTupleIndexes)
|
self.VarTupleIndex = list(varTupleIndexes)
|
||||||
tupleCount = self.VarTupleCount = len(self.VarTupleIndex)
|
tupleCount = self.VarTupleCount = len(self.VarTupleIndex)
|
||||||
records = self.Item = []
|
records = self.Item = []
|
||||||
for item in items:
|
for item in items:
|
||||||
assert len(item) == tupleCount
|
assert len(item) == tupleCount
|
||||||
record = ot.VarItemByteRecord() if self.format == 1 else ot.VarItemShortRecord()
|
record = ot.VarItemByteRecord() if self.Format == 1 else ot.VarItemShortRecord()
|
||||||
record.deltas = list(item)
|
record.Deltas = list(item)
|
||||||
records.append(record)
|
records.append(record)
|
||||||
self.ItemCount = len(self.Item)
|
self.ItemCount = len(self.Item)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def buildVarStore(varTupleList, varDeltas):
|
def buildVarStore(varTupleList, varDeltasList):
|
||||||
self = ot.VarStore()
|
self = ot.VarStore()
|
||||||
|
self.Format = 1
|
||||||
self.VarTupleList = varTupleList
|
self.VarTupleList = varTupleList
|
||||||
self.VarDeltas = varDeltas
|
self.VarDeltas = list(varDeltasList)
|
||||||
self.VarDeltasCount = len(self.VarDeltas)
|
self.VarDeltasCount = len(self.VarDeltas)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user