[VARC/scaleUpem] Implement

This commit is contained in:
Behdad Esfahbod 2023-12-17 17:39:13 -07:00
parent febbb34dba
commit 0f0148e54a
4 changed files with 1328 additions and 1823 deletions

View File

@ -10,7 +10,10 @@ import fontTools.ttLib.tables.otTables as otTables
from fontTools.cffLib import VarStoreData
import fontTools.cffLib.specializer as cffSpecializer
from fontTools.varLib import builder # for VarData.calculateNumShorts
from fontTools.varLib.multiVarStore import OnlineMultiVarStoreBuilder
from fontTools.misc.vector import Vector
from fontTools.misc.fixedTools import otRound
from itertools import batched
__all__ = ["scale_upem", "ScalerVisitor"]
@ -145,6 +148,13 @@ def visit(visitor, obj, attr, variations):
@ScalerVisitor.register_attr(ttLib.getTableClass("VARC"), "table")
def visit(visitor, obj, attr, varc):
# VarComposite variations are a pain
fvar = visitor.font["fvar"]
fvarAxes = [a.axisTag for a in fvar.axes]
store = varc.MultiVarStore
storeBuilder = OnlineMultiVarStoreBuilder(fvarAxes)
for g in varc.VarCompositeGlyphs.glyphs:
for component in g.components:
t = component.transform
@ -153,7 +163,75 @@ def visit(visitor, obj, attr, varc):
t.tCenterX = visitor.scale(t.tCenterX)
t.tCenterY = visitor.scale(t.tCenterY)
# TODO: MultiVarStore
if component.flags & otTables.VarComponentFlags.AXIS_VALUES_HAVE_VARIATION:
varIdx = component.locationVarIndex
if varIdx == otTables.NO_VARIATION_INDEX:
continue
major = varIdx >> 16
minor = varIdx & 0xFFFF
varData = store.MultiVarData[major]
vec = varData.Item[minor]
storeBuilder.setSupports(store.get_supports(major, fvar.axes))
if vec.values:
m = len(vec.values) // varData.VarRegionCount
vec = list(batched(vec.values, m))
vec = [Vector(v) for v in vec]
component.locationVarIndex = storeBuilder.storeDeltas(vec)
else:
component.transformVarIndex = otTables.NO_VARIATION_INDEX
if component.flags & otTables.VarComponentFlags.TRANSFORM_HAS_VARIATION:
varIdx = component.transformVarIndex
if varIdx == otTables.NO_VARIATION_INDEX:
continue
major = varIdx >> 16
minor = varIdx & 0xFFFF
vec = varData.Item[varIdx & 0xFFFF]
major = varIdx >> 16
minor = varIdx & 0xFFFF
varData = store.MultiVarData[major]
vec = varData.Item[minor]
storeBuilder.setSupports(store.get_supports(major, fvar.axes))
if vec.values:
m = len(vec.values) // varData.VarRegionCount
flags = component.flags
vec = list(batched(vec.values, m))
newVec = []
for v in vec:
v = list(v)
i = 0
## Scale translate & tCenter
if flags & otTables.VarComponentFlags.HAVE_TRANSLATE_X:
v[i] = visitor.scale(v[i])
i += 1
if flags & otTables.VarComponentFlags.HAVE_TRANSLATE_Y:
v[i] = visitor.scale(v[i])
i += 1
if flags & otTables.VarComponentFlags.HAVE_ROTATION:
i += 1
if flags & otTables.VarComponentFlags.HAVE_SCALE_X:
i += 1
if flags & otTables.VarComponentFlags.HAVE_SCALE_Y:
i += 1
if flags & otTables.VarComponentFlags.HAVE_SKEW_X:
i += 1
if flags & otTables.VarComponentFlags.HAVE_SKEW_Y:
i += 1
if flags & otTables.VarComponentFlags.HAVE_TCENTER_X:
v[i] = visitor.scale(v[i])
i += 1
if flags & otTables.VarComponentFlags.HAVE_TCENTER_Y:
v[i] = visitor.scale(v[i])
i += 1
newVec.append(Vector(v))
vec = newVec
component.transformVarIndex = storeBuilder.storeDeltas(vec)
else:
component.transformVarIndex = otTables.NO_VARIATION_INDEX
varc.MultiVarStore = storeBuilder.finish()
@ScalerVisitor.register_attr(ttLib.getTableClass("kern"), "kernTables")

View File

@ -205,6 +205,17 @@ def MultiVarStore_prune_regions(self, *, VarData="VarData"):
ot.MultiVarStore.prune_regions = MultiVarStore_prune_regions
ot.MultiVarStore.subset_varidxes = MultiVarStore_subset_varidxes
def MultiVarStore_get_supports(self, major, fvarAxes):
supports = []
varData = self.MultiVarData[major]
for regionIdx in varData.VarRegionIndex:
region = self.VarRegionList.Region[regionIdx]
support = region.get_support(fvarAxes)
supports.append(support)
return supports
ot.MultiVarStore.get_supports = MultiVarStore_get_supports
def VARC_collect_varidxes(self, varidxes):
for glyph in self.VarCompositeGlyphs.glyphs:

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
from fontTools.ttLib import TTFont
from fontTools.ttLib.scaleUpem import scale_upem
from io import BytesIO
import difflib
import os
import shutil
@ -70,6 +71,12 @@ class ScaleUpemTest(unittest.TestCase):
scale_upem(font, 500)
# Save / load to ensure calculated values are correct
# XXX This wans't needed before. So needs investigation.
iobytes = BytesIO()
font.save(iobytes)
# Just saving is enough to fix the numbers. Sigh...
expected_ttx_path = self.get_path("varc-ac00-ac01-500upem.ttx")
self.expect_ttx(font, expected_ttx_path, tables)