[subset/VARC] Subset MultiVarStore

This commit is contained in:
Behdad Esfahbod 2023-12-17 10:52:43 -07:00
parent f37f2e4a03
commit 5c278464e0
3 changed files with 75 additions and 16 deletions

View File

@ -14,7 +14,7 @@ from fontTools.misc.cliTools import makeOutputFileName
from fontTools.subset.util import _add_method, _uniq_sort
from fontTools.subset.cff import *
from fontTools.subset.svg import *
from fontTools.varLib import varStore # for subset_varidxes
from fontTools.varLib import varStore, multiVarStore # For monkey-patching
from fontTools.ttLib.tables._n_a_m_e import NameRecordVisitor
import sys
import struct
@ -2629,13 +2629,17 @@ def closure_glyphs(self, s):
s.glyphs.update(variants)
@_add_method(ttLib.getTableClass("VARC"))
def subset_glyphs(self, s):
indices = self.table.Coverage.subset(s.glyphs)
# TODO Subset MultiVarStore
self.table.VarCompositeGlyphs.glyphs = _list_subset(self.table.VarCompositeGlyphs.glyphs, indices)
self.table.VarCompositeGlyphs.glyphs = _list_subset(
self.table.VarCompositeGlyphs.glyphs, indices
)
return bool(self.table.VarCompositeGlyphs.glyphs)
@_add_method(ttLib.getTableClass("VARC"))
def closure_glyphs(self, s):
if self.table.VarCompositeGlyphs:
@ -2650,6 +2654,30 @@ def closure_glyphs(self, s):
glyphs.add(name)
new.add(name)
@_add_method(ttLib.getTableClass("VARC"))
def prune_post_subset(self, font, options):
table = self.table
if not hasattr(table, "MultiVarStore"):
return True
store = table.MultiVarStore
usedVarIdxes = set()
# Collect.
table.collect_varidxes(usedVarIdxes)
# Subset.
varidx_map = store.subset_varidxes(usedVarIdxes)
# Map.
table.remap_varidxes(varidx_map)
return True
@_add_method(ttLib.getTableClass("MATH"))
def closure_glyphs(self, s):
if self.table.MathVariants:

View File

@ -3,6 +3,7 @@ from fontTools.misc.intTools import bit_count
from fontTools.misc.vector import Vector
from fontTools.ttLib.tables import otTables as ot
from fontTools.varLib.models import supportScalar
import fontTools.varLib.varStore # For monkey-patching
from fontTools.varLib.builder import (
buildVarRegionList,
buildVarRegion,
@ -191,3 +192,29 @@ class MultiVarStoreInstancer(object):
varData = self._varData
scalars = [self._getScalar(ri) for ri in varData[varDataIndex].VarRegionIndex]
return self.interpolateFromDeltasAndScalars(deltas, scalars)
def MultiVarStore_subset_varidxes(self, varIdxes):
return ot.VarStore.subset_varidxes(self, varIdxes, VarData="MultiVarData")
ot.MultiVarStore.prune_regions = ot.VarStore.prune_regions
ot.MultiVarStore.subset_varidxes = MultiVarStore_subset_varidxes
def VARC_collect_varidxes(self, varidxes):
for glyph in self.VarCompositeGlyphs.glyphs:
for component in glyph.components:
varidxes.add(component.locationVarIndex)
varidxes.add(component.transformVarIndex)
def VARC_remap_varidxes(self, varidxes_map):
for glyph in self.VarCompositeGlyphs.glyphs:
for component in glyph.components:
component.locationVarIndex = varidxes_map[component.locationVarIndex]
component.transformVarIndex = varidxes_map[component.transformVarIndex]
ot.VARC.collect_varidxes = VARC_collect_varidxes
ot.VARC.remap_varidxes = VARC_remap_varidxes

View File

@ -246,26 +246,29 @@ class VarStoreInstancer(object):
def VarStore_subset_varidxes(
self, varIdxes, optimize=True, retainFirstMap=False, advIdxes=set()
self,
varIdxes,
optimize=True,
retainFirstMap=False,
advIdxes=set(),
*,
VarData="VarData",
):
# Sort out used varIdxes by major/minor.
used = {}
used = defaultdict(set)
for varIdx in varIdxes:
if varIdx == NO_VARIATION_INDEX:
continue
major = varIdx >> 16
minor = varIdx & 0xFFFF
d = used.get(major)
if d is None:
d = used[major] = set()
d.add(minor)
used[major].add(minor)
del varIdxes
#
# Subset VarData
#
varData = self.VarData
varData = getattr(self, VarData)
newVarData = []
varDataMap = {NO_VARIATION_INDEX: NO_VARIATION_INDEX}
for major, data in enumerate(varData):
@ -296,12 +299,13 @@ def VarStore_subset_varidxes(
data.Item = newItems
data.ItemCount = len(data.Item)
data.calculateNumShorts(optimize=optimize)
if VarData == "VarData":
data.calculateNumShorts(optimize=optimize)
self.VarData = newVarData
self.VarDataCount = len(self.VarData)
setattr(self, VarData, newVarData)
setattr(self, VarData + "Count", len(newVarData))
self.prune_regions()
self.prune_regions(VarData=VarData)
return varDataMap
@ -309,7 +313,7 @@ def VarStore_subset_varidxes(
ot.VarStore.subset_varidxes = VarStore_subset_varidxes
def VarStore_prune_regions(self):
def VarStore_prune_regions(self, *, VarData="VarData"):
"""Remove unused VarRegions."""
#
# Subset VarRegionList
@ -317,7 +321,7 @@ def VarStore_prune_regions(self):
# Collect.
usedRegions = set()
for data in self.VarData:
for data in getattr(self, VarData):
usedRegions.update(data.VarRegionIndex)
# Subset.
regionList = self.VarRegionList
@ -330,7 +334,7 @@ def VarStore_prune_regions(self):
regionList.Region = newRegions
regionList.RegionCount = len(regionList.Region)
# Map.
for data in self.VarData:
for data in getattr(self, VarData):
data.VarRegionIndex = [regionMap[i] for i in data.VarRegionIndex]