Skip to content

Commit

Permalink
[varLib] Add avarPlanner
Browse files Browse the repository at this point in the history
  • Loading branch information
behdad committed Jul 23, 2023
1 parent b1ac5aa commit a9bf16f
Showing 1 changed file with 120 additions and 0 deletions.
120 changes: 120 additions & 0 deletions Lib/fontTools/varLib/avarPlanner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
from fontTools.pens.areaPen import AreaPen
from fontTools.varLib.models import piecewiseLinearMap
from math import exp, log

WEIGHTS = [100, 200, 300, 400, 500, 600, 700, 800, 900]

SAMPLES = 8


def getGlyphsetWeight(glyphset):
wght_sum = wdth_sum = 0

Check warning on line 11 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L11

Added line #L11 was not covered by tests
for glyph_name in glyphset:
glyph = glyphset[glyph_name]

Check warning on line 13 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L13

Added line #L13 was not covered by tests

pen = AreaPen(glyphset=glyphset)
glyph.draw(pen)

Check warning on line 16 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L15-L16

Added lines #L15 - L16 were not covered by tests

wght_sum += abs(pen.value)
wdth_sum += glyph.width

Check warning on line 19 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L18-L19

Added lines #L18 - L19 were not covered by tests

return wght_sum / wdth_sum

Check warning on line 21 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L21

Added line #L21 was not covered by tests


def planWeightAxis(font, minValue, defaultValue, maxValue, weights=WEIGHTS):
print("Weight min/default/max:", minValue, defaultValue, maxValue)

Check warning on line 25 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L25

Added line #L25 was not covered by tests

out = {}
outNormalized = {}

Check warning on line 28 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L27-L28

Added lines #L27 - L28 were not covered by tests

upem = font["head"].unitsPerEm
axisWeightAverage = {}

Check warning on line 31 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L30-L31

Added lines #L30 - L31 were not covered by tests
for weight in sorted({minValue, defaultValue, maxValue}):
glyphset = font.getGlyphSet(location={"wght": weight})
axisWeightAverage[weight] = getGlyphsetWeight(glyphset) / upem

Check warning on line 34 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L33-L34

Added lines #L33 - L34 were not covered by tests

print("Calculated average glyph black ratio:", axisWeightAverage)

Check warning on line 36 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L36

Added line #L36 was not covered by tests

outNormalized[-1] = -1

Check warning on line 38 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L38

Added line #L38 was not covered by tests
for extremeValue in sorted({minValue, maxValue} - {defaultValue}):
rangeMin = min(defaultValue, extremeValue)
rangeMax = max(defaultValue, extremeValue)

Check warning on line 41 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L40-L41

Added lines #L40 - L41 were not covered by tests
targetWeights = {w for w in weights if rangeMin < w < rangeMax}
if not targetWeights:
continue

Check warning on line 44 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L44

Added line #L44 was not covered by tests

bias = -1 if extremeValue < defaultValue else 0

Check warning on line 46 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L46

Added line #L46 was not covered by tests

print("Planning target weights", targetWeights)
print("Sampling", SAMPLES, "points in range", rangeMin, rangeMax)
weightBlackRatio = axisWeightAverage.copy()

Check warning on line 50 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L48-L50

Added lines #L48 - L50 were not covered by tests
for sample in range(1, SAMPLES + 1):
weight = rangeMin + (rangeMax - rangeMin) * sample / (SAMPLES + 1)
print("Sampling weight", weight)
glyphset = font.getGlyphSet(location={"wght": weight})
weightBlackRatio[weight] = getGlyphsetWeight(glyphset) / upem
print("Sampled average glyph black ratio:", weightBlackRatio)

Check warning on line 56 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L52-L56

Added lines #L52 - L56 were not covered by tests

blackRatioWeight = {}

Check warning on line 58 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L58

Added line #L58 was not covered by tests
for weight in sorted(weightBlackRatio):
blackRatioWeight[weightBlackRatio[weight]] = weight

Check warning on line 60 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L60

Added line #L60 was not covered by tests

logMin = log(weightBlackRatio[rangeMin])
logMax = log(weightBlackRatio[rangeMax])
out[rangeMin] = rangeMin
outNormalized[bias] = bias

Check warning on line 65 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L62-L65

Added lines #L62 - L65 were not covered by tests
for weight in sorted(targetWeights):
t = (weight - rangeMin) / (rangeMax - rangeMin)
targetBlackRatio = exp(logMin + t * (logMax - logMin))
targetWeight = piecewiseLinearMap(targetBlackRatio, blackRatioWeight)
print("Planned mapping weight %g to %g" % (weight, targetWeight))
out[weight] = targetWeight
outNormalized[t + bias] = (targetWeight - rangeMin) / (

Check warning on line 72 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L67-L72

Added lines #L67 - L72 were not covered by tests
rangeMax - rangeMin
) + bias
out[rangeMax] = rangeMax
outNormalized[bias + 1] = bias + 1
outNormalized[+1] = +1

Check warning on line 77 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L75-L77

Added lines #L75 - L77 were not covered by tests

print("Planned mapping:", out)
print("Planned normalized mapping:", outNormalized)
return out, outNormalized

Check warning on line 81 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L79-L81

Added lines #L79 - L81 were not covered by tests


def main(args=None):
if args is None:
import sys

Check warning on line 86 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L86

Added line #L86 was not covered by tests

args = sys.argv[1:]

Check warning on line 88 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L88

Added line #L88 was not covered by tests

from fontTools.ttLib import TTFont
import argparse

Check warning on line 91 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L90-L91

Added lines #L90 - L91 were not covered by tests

parser = argparse.ArgumentParser(

Check warning on line 93 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L93

Added line #L93 was not covered by tests
"fonttools varLib.avarPlanner",
description="Plan `avar` table for variable font",
)
parser.add_argument("font", metavar="font.ttf", help="Font file.")

Check warning on line 97 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L97

Added line #L97 was not covered by tests

options = parser.parse_args(args)

Check warning on line 99 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L99

Added line #L99 was not covered by tests

font = TTFont(options.font)
fvar = font["fvar"]
wghtAxis = slntAxis = None

Check warning on line 103 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L101-L103

Added lines #L101 - L103 were not covered by tests
for axis in fvar.axes:
if axis.axisTag == "wght":
wghtAxis = axis

Check warning on line 106 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L106

Added line #L106 was not covered by tests
elif axis.axisTag == "slnt":
slntAxis = axis

Check warning on line 108 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L108

Added line #L108 was not covered by tests

_, mapping = planWeightAxis(

Check warning on line 110 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L110

Added line #L110 was not covered by tests
font, wghtAxis.minValue, wghtAxis.defaultValue, wghtAxis.maxValue
)
if "avar" in font:
print("Existing weight mapping:", font["avar"].segments["wght"])

Check warning on line 114 in Lib/fontTools/varLib/avarPlanner.py

View check run for this annotation

Codecov / codecov/patch

Lib/fontTools/varLib/avarPlanner.py#L114

Added line #L114 was not covered by tests


if __name__ == "__main__":
import sys

sys.exit(main())

0 comments on commit a9bf16f

Please sign in to comment.