[varLib] Generate direct HVAR
This commit is contained in:
parent
e2da17e032
commit
c1717224da
@ -89,7 +89,7 @@ class BaseConverter(object):
|
||||
self.tableClass = tableClass
|
||||
self.isCount = name.endswith("Count")
|
||||
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):
|
||||
"""Read an array of values from the reader."""
|
||||
@ -230,9 +230,19 @@ class GlyphID(SimpleValue):
|
||||
class VarAxisID(SimpleValue):
|
||||
staticSize = 2
|
||||
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):
|
||||
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):
|
||||
def xmlRead(self, attrs, content, font):
|
||||
@ -509,9 +519,11 @@ converterMapping = {
|
||||
"GlyphID": GlyphID,
|
||||
"DeciPoints": DeciPoints,
|
||||
"Fixed": Fixed,
|
||||
"F2Dot14": F2Dot14,
|
||||
"struct": Struct,
|
||||
"Offset": Table,
|
||||
"LOffset": LTable,
|
||||
"ValueRecord": ValueRecord,
|
||||
"VarAxisID": VarAxisID,
|
||||
"DeltaValue": DeltaValue,
|
||||
}
|
||||
|
@ -845,7 +845,7 @@ otData = [
|
||||
# VariationStore
|
||||
|
||||
('VarAxis', [
|
||||
('uint16', 'VarAxisID', None, None, ''),
|
||||
('VarAxisID', 'VarAxisID', None, None, ''),
|
||||
('F2Dot14', 'StartCoord', None, None, ''),
|
||||
('F2Dot14', 'PeakCoord', None, None, ''),
|
||||
('F2Dot14', 'EndCoord', None, None, ''),
|
||||
@ -862,10 +862,10 @@ otData = [
|
||||
]),
|
||||
|
||||
('VarItemByteRecord', [
|
||||
('int8', 'deltas', 'VarTupleCount', 0, ''),
|
||||
('int8', 'Deltas', 'VarTupleCount', 0, ''),
|
||||
]),
|
||||
('VarItemShortRecord', [
|
||||
('int16', 'deltas', 'VarTupleCount', 0, ''),
|
||||
('int16', 'Deltas', 'VarTupleCount', 0, ''),
|
||||
]),
|
||||
|
||||
('VarDeltasFormat1', [
|
||||
|
@ -20,11 +20,12 @@ API *will* change in near future.
|
||||
"""
|
||||
from __future__ import print_function, division, absolute_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._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_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
|
||||
import warnings
|
||||
try:
|
||||
@ -317,7 +318,7 @@ def _AddName(font, name):
|
||||
# Move to fvar table proper?
|
||||
def _add_fvar(font, axes, instances):
|
||||
assert "fvar" not in font
|
||||
font['fvar'] = fvar = table__f_v_a_r()
|
||||
font['fvar'] = fvar = newTable('fvar')
|
||||
|
||||
for tag in sorted(axes.keys()):
|
||||
axis = Axis()
|
||||
@ -430,7 +431,7 @@ def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):
|
||||
|
||||
print("Generating gvar")
|
||||
assert "gvar" not in font
|
||||
gvar = font["gvar"] = table__g_v_a_r()
|
||||
gvar = font["gvar"] = newTable('gvar')
|
||||
gvar.version = 1
|
||||
gvar.reserved = 0
|
||||
gvar.variations = {}
|
||||
@ -440,28 +441,56 @@ def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):
|
||||
model_base_idx = model.mapping[base_idx]
|
||||
assert 0 == model_base_idx
|
||||
|
||||
hAdvanceDeltas = {}
|
||||
|
||||
for glyph in font.getGlyphOrder():
|
||||
|
||||
allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
|
||||
allCoords = [d[0] 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]
|
||||
if (any(c != control for c in allControls)):
|
||||
warnings.warn("glyph %s has incompatible masters; skipping" % glyph)
|
||||
continue
|
||||
del allControls
|
||||
|
||||
# Update gvar
|
||||
gvar.variations[glyph] = []
|
||||
|
||||
deltas = model.getDeltas(allCoords)
|
||||
supports = model.supports
|
||||
assert len(deltas) == len(supports)
|
||||
for i,(delta,support) in enumerate(zip(deltas, supports)):
|
||||
if i == model_base_idx:
|
||||
continue
|
||||
for i,(delta,support) in enumerate(zip(deltas[1:], supports[1:])):
|
||||
var = GlyphVariation(support, delta)
|
||||
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):
|
||||
|
||||
import sys
|
||||
|
@ -28,22 +28,23 @@ def buildVarTupleList(supports):
|
||||
|
||||
def buildVarDeltas(varTupleIndexes, items):
|
||||
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)
|
||||
tupleCount = self.VarTupleCount = len(self.VarTupleIndex)
|
||||
records = self.Item = []
|
||||
for item in items:
|
||||
assert len(item) == tupleCount
|
||||
record = ot.VarItemByteRecord() if self.format == 1 else ot.VarItemShortRecord()
|
||||
record.deltas = list(item)
|
||||
record = ot.VarItemByteRecord() if self.Format == 1 else ot.VarItemShortRecord()
|
||||
record.Deltas = list(item)
|
||||
records.append(record)
|
||||
self.ItemCount = len(self.Item)
|
||||
return self
|
||||
|
||||
def buildVarStore(varTupleList, varDeltas):
|
||||
def buildVarStore(varTupleList, varDeltasList):
|
||||
self = ot.VarStore()
|
||||
self.Format = 1
|
||||
self.VarTupleList = varTupleList
|
||||
self.VarDeltas = varDeltas
|
||||
self.VarDeltas = list(varDeltasList)
|
||||
self.VarDeltasCount = len(self.VarDeltas)
|
||||
return self
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user