[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.util import _add_method, _uniq_sort
from fontTools.subset.cff import * from fontTools.subset.cff import *
from fontTools.subset.svg 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 from fontTools.ttLib.tables._n_a_m_e import NameRecordVisitor
import sys import sys
import struct import struct
@ -2629,13 +2629,17 @@ def closure_glyphs(self, s):
s.glyphs.update(variants) s.glyphs.update(variants)
@_add_method(ttLib.getTableClass("VARC")) @_add_method(ttLib.getTableClass("VARC"))
def subset_glyphs(self, s): def subset_glyphs(self, s):
indices = self.table.Coverage.subset(s.glyphs) indices = self.table.Coverage.subset(s.glyphs)
# TODO Subset MultiVarStore # 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) return bool(self.table.VarCompositeGlyphs.glyphs)
@_add_method(ttLib.getTableClass("VARC")) @_add_method(ttLib.getTableClass("VARC"))
def closure_glyphs(self, s): def closure_glyphs(self, s):
if self.table.VarCompositeGlyphs: if self.table.VarCompositeGlyphs:
@ -2650,6 +2654,30 @@ def closure_glyphs(self, s):
glyphs.add(name) glyphs.add(name)
new.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")) @_add_method(ttLib.getTableClass("MATH"))
def closure_glyphs(self, s): def closure_glyphs(self, s):
if self.table.MathVariants: 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.misc.vector import Vector
from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables import otTables as ot
from fontTools.varLib.models import supportScalar from fontTools.varLib.models import supportScalar
import fontTools.varLib.varStore # For monkey-patching
from fontTools.varLib.builder import ( from fontTools.varLib.builder import (
buildVarRegionList, buildVarRegionList,
buildVarRegion, buildVarRegion,
@ -191,3 +192,29 @@ class MultiVarStoreInstancer(object):
varData = self._varData varData = self._varData
scalars = [self._getScalar(ri) for ri in varData[varDataIndex].VarRegionIndex] scalars = [self._getScalar(ri) for ri in varData[varDataIndex].VarRegionIndex]
return self.interpolateFromDeltasAndScalars(deltas, scalars) 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( 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. # Sort out used varIdxes by major/minor.
used = {} used = defaultdict(set)
for varIdx in varIdxes: for varIdx in varIdxes:
if varIdx == NO_VARIATION_INDEX: if varIdx == NO_VARIATION_INDEX:
continue continue
major = varIdx >> 16 major = varIdx >> 16
minor = varIdx & 0xFFFF minor = varIdx & 0xFFFF
d = used.get(major) used[major].add(minor)
if d is None:
d = used[major] = set()
d.add(minor)
del varIdxes del varIdxes
# #
# Subset VarData # Subset VarData
# #
varData = self.VarData varData = getattr(self, VarData)
newVarData = [] newVarData = []
varDataMap = {NO_VARIATION_INDEX: NO_VARIATION_INDEX} varDataMap = {NO_VARIATION_INDEX: NO_VARIATION_INDEX}
for major, data in enumerate(varData): for major, data in enumerate(varData):
@ -296,12 +299,13 @@ def VarStore_subset_varidxes(
data.Item = newItems data.Item = newItems
data.ItemCount = len(data.Item) data.ItemCount = len(data.Item)
data.calculateNumShorts(optimize=optimize) if VarData == "VarData":
data.calculateNumShorts(optimize=optimize)
self.VarData = newVarData setattr(self, VarData, newVarData)
self.VarDataCount = len(self.VarData) setattr(self, VarData + "Count", len(newVarData))
self.prune_regions() self.prune_regions(VarData=VarData)
return varDataMap return varDataMap
@ -309,7 +313,7 @@ def VarStore_subset_varidxes(
ot.VarStore.subset_varidxes = 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.""" """Remove unused VarRegions."""
# #
# Subset VarRegionList # Subset VarRegionList
@ -317,7 +321,7 @@ def VarStore_prune_regions(self):
# Collect. # Collect.
usedRegions = set() usedRegions = set()
for data in self.VarData: for data in getattr(self, VarData):
usedRegions.update(data.VarRegionIndex) usedRegions.update(data.VarRegionIndex)
# Subset. # Subset.
regionList = self.VarRegionList regionList = self.VarRegionList
@ -330,7 +334,7 @@ def VarStore_prune_regions(self):
regionList.Region = newRegions regionList.Region = newRegions
regionList.RegionCount = len(regionList.Region) regionList.RegionCount = len(regionList.Region)
# Map. # Map.
for data in self.VarData: for data in getattr(self, VarData):
data.VarRegionIndex = [regionMap[i] for i in data.VarRegionIndex] data.VarRegionIndex = [regionMap[i] for i in data.VarRegionIndex]