diff --git a/Lib/fontTools/colorLib/geometry.py b/Lib/fontTools/colorLib/geometry.py index ec6475357..e62aead1c 100644 --- a/Lib/fontTools/colorLib/geometry.py +++ b/Lib/fontTools/colorLib/geometry.py @@ -1,7 +1,7 @@ """Helpers for manipulating 2D points and vectors in COLR table.""" from math import copysign, cos, hypot, pi -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound def _vector_between(origin, target): diff --git a/Lib/fontTools/colorLib/table_builder.py b/Lib/fontTools/colorLib/table_builder.py index 18e2de181..6fba6b0fc 100644 --- a/Lib/fontTools/colorLib/table_builder.py +++ b/Lib/fontTools/colorLib/table_builder.py @@ -22,7 +22,7 @@ from fontTools.ttLib.tables.otConverters import ( IntValue, FloatValue, ) -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound class BuildCallback(enum.Enum): diff --git a/Lib/fontTools/misc/arrayTools.py b/Lib/fontTools/misc/arrayTools.py index 4b5f08298..9a64b2929 100644 --- a/Lib/fontTools/misc/arrayTools.py +++ b/Lib/fontTools/misc/arrayTools.py @@ -3,7 +3,7 @@ so on. """ from fontTools.misc.py23 import * -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools.misc.vector import Vector as _Vector import math import warnings diff --git a/Lib/fontTools/misc/fixedTools.py b/Lib/fontTools/misc/fixedTools.py index 931b665e2..eda81c33c 100644 --- a/Lib/fontTools/misc/fixedTools.py +++ b/Lib/fontTools/misc/fixedTools.py @@ -18,6 +18,7 @@ functions for converting between fixed-point, float and string representations. """ from fontTools.misc.py23 import * +from .roundTools import otRound import math import logging @@ -25,7 +26,6 @@ log = logging.getLogger(__name__) __all__ = [ "MAX_F2DOT14", - "otRound", "fixedToFloat", "floatToFixed", "floatToFixedToFloat", @@ -41,30 +41,6 @@ __all__ = [ MAX_F2DOT14 = 0x7FFF / (1 << 14) -def otRound(value): - """Round float value to nearest integer towards ``+Infinity``. - - The OpenType spec (in the section on `"normalization" of OpenType Font Variations `_) - defines the required method for converting floating point values to - fixed-point. In particular it specifies the following rounding strategy: - - for fractional values of 0.5 and higher, take the next higher integer; - for other fractional values, truncate. - - This function rounds the floating-point value according to this strategy - in preparation for conversion to fixed-point. - - Args: - value (float): The input floating-point value. - - Returns - float: The rounded value. - """ - # See this thread for how we ended up with this implementation: - # https://github.com/fonttools/fonttools/issues/1248#issuecomment-383198166 - return int(math.floor(value + 0.5)) - - def fixedToFloat(value, precisionBits): """Converts a fixed-point number to a float given the number of precision bits. diff --git a/Lib/fontTools/misc/roundTools.py b/Lib/fontTools/misc/roundTools.py new file mode 100644 index 000000000..c1d546f1f --- /dev/null +++ b/Lib/fontTools/misc/roundTools.py @@ -0,0 +1,58 @@ +""" +Various round-to-integer helpers. +""" + +import math +import functools +import logging + +log = logging.getLogger(__name__) + +__all__ = [ + "noRound", + "otRound", + "maybeRound", + "roundFunc", +] + +def noRound(value): + return value + +def otRound(value): + """Round float value to nearest integer towards ``+Infinity``. + + The OpenType spec (in the section on `"normalization" of OpenType Font Variations `_) + defines the required method for converting floating point values to + fixed-point. In particular it specifies the following rounding strategy: + + for fractional values of 0.5 and higher, take the next higher integer; + for other fractional values, truncate. + + This function rounds the floating-point value according to this strategy + in preparation for conversion to fixed-point. + + Args: + value (float): The input floating-point value. + + Returns + float: The rounded value. + """ + # See this thread for how we ended up with this implementation: + # https://github.com/fonttools/fonttools/issues/1248#issuecomment-383198166 + return int(math.floor(value + 0.5)) + +def maybeRound(v, tolerance, round=otRound): + rounded = round(v) + return rounded if abs(rounded - v) <= tolerance else v + +def roundFunc(tolerance, round=otRound): + if tolerance < 0: + raise ValueError("Rounding tolerance must be positive") + + if tolerance == 0: + return noRound + + if tolerance >= .5: + return round + + return functools.partial(maybeRound, tolerance=tolerance, round=round) diff --git a/Lib/fontTools/misc/vector.py b/Lib/fontTools/misc/vector.py index 98d4ca0fe..81c148418 100644 --- a/Lib/fontTools/misc/vector.py +++ b/Lib/fontTools/misc/vector.py @@ -76,7 +76,7 @@ class Vector(tuple): def __neg__(self): return self._unaryOp(operator.neg) - def __round__(self): + def __round__(self, *, round=round): return self._unaryOp(round) def __eq__(self, other): diff --git a/Lib/fontTools/pens/roundingPen.py b/Lib/fontTools/pens/roundingPen.py index c032cad1f..2a7c476c3 100644 --- a/Lib/fontTools/pens/roundingPen.py +++ b/Lib/fontTools/pens/roundingPen.py @@ -1,4 +1,4 @@ -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools.misc.transform import Transform from fontTools.pens.filterPen import FilterPen, FilterPointPen diff --git a/Lib/fontTools/pens/t2CharStringPen.py b/Lib/fontTools/pens/t2CharStringPen.py index a4b1d8f67..0fddec1ae 100644 --- a/Lib/fontTools/pens/t2CharStringPen.py +++ b/Lib/fontTools/pens/t2CharStringPen.py @@ -1,36 +1,12 @@ # Copyright (c) 2009 Type Supply LLC # Author: Tal Leming -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound, roundFunc from fontTools.misc.psCharStrings import T2CharString from fontTools.pens.basePen import BasePen from fontTools.cffLib.specializer import specializeCommands, commandsToProgram -def t2c_round(number, tolerance=0.5): - if tolerance == 0: - return number # no-op - rounded = otRound(number) - # return rounded integer if the tolerance >= 0.5, or if the absolute - # difference between the original float and the rounded integer is - # within the tolerance - if tolerance >= .5 or abs(rounded - number) <= tolerance: - return rounded - else: - # else return the value un-rounded - return number - -def makeRoundFunc(tolerance): - if tolerance < 0: - raise ValueError("Rounding tolerance must be positive") - - def roundPoint(point): - x, y = point - return t2c_round(x, tolerance), t2c_round(y, tolerance) - - return roundPoint - - class T2CharStringPen(BasePen): """Pen to draw Type 2 CharStrings. @@ -44,7 +20,7 @@ class T2CharStringPen(BasePen): def __init__(self, width, glyphSet, roundTolerance=0.5, CFF2=False): super(T2CharStringPen, self).__init__(glyphSet) - self.roundPoint = makeRoundFunc(roundTolerance) + self.round = roundFunc(roundTolerance) self._CFF2 = CFF2 self._width = width self._commands = [] @@ -52,7 +28,7 @@ class T2CharStringPen(BasePen): def _p(self, pt): p0 = self._p0 - pt = self._p0 = self.roundPoint(pt) + pt = self._p0 = (self.round(pt[0]), self.round(pt[1])) return [pt[0]-p0[0], pt[1]-p0[1]] def _moveTo(self, pt): diff --git a/Lib/fontTools/pens/ttGlyphPen.py b/Lib/fontTools/pens/ttGlyphPen.py index f493f1acc..e7841efcb 100644 --- a/Lib/fontTools/pens/ttGlyphPen.py +++ b/Lib/fontTools/pens/ttGlyphPen.py @@ -1,5 +1,6 @@ from array import array from fontTools.misc.fixedTools import MAX_F2DOT14, otRound, floatToFixedToFloat +from fontTools.misc.roundTools import otRound from fontTools.pens.basePen import LoggingPen from fontTools.pens.transformPen import TransformPen from fontTools.ttLib.tables import ttProgram diff --git a/Lib/fontTools/subset/__init__.py b/Lib/fontTools/subset/__init__.py index 8162c09c2..c2d402162 100644 --- a/Lib/fontTools/subset/__init__.py +++ b/Lib/fontTools/subset/__init__.py @@ -2,7 +2,7 @@ # # Google Author(s): Behdad Esfahbod -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools import ttLib from fontTools.ttLib.tables import otTables from fontTools.otlLib.maxContextCalc import maxCtxFont diff --git a/Lib/fontTools/subset/cff.py b/Lib/fontTools/subset/cff.py index 7db6d880a..b59c6b96d 100644 --- a/Lib/fontTools/subset/cff.py +++ b/Lib/fontTools/subset/cff.py @@ -1,7 +1,7 @@ from fontTools.misc import psCharStrings from fontTools import ttLib from fontTools.pens.basePen import NullPen -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools.varLib.varStore import VarStoreInstancer def _add_method(*clazzes): diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py index e12969e40..b8ed20d5e 100644 --- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py +++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py @@ -1506,12 +1506,12 @@ class GlyphCoordinates(object): p = self._checkFloat(p) self._a.extend(p) - def toInt(self): + def toInt(self, *, round=otRound): if not self.isFloat(): return a = array.array("h") for n in self._a: - a.append(otRound(n)) + a.append(round(n)) self._a = a def relativeToAbsolute(self): @@ -1626,13 +1626,9 @@ class GlyphCoordinates(object): for i in range(len(a)): a[i] = -a[i] return r - def __round__(self): - """ - Note: This is Python 3 only. Python 2 does not call __round__. - As such, we cannot test this method either. :( - """ + def __round__(self, *, round=otRound): r = self.copy() - r.toInt() + r.toInt(round=round) return r def __add__(self, other): return self.copy().__iadd__(other) diff --git a/Lib/fontTools/ttLib/tables/_h_m_t_x.py b/Lib/fontTools/ttLib/tables/_h_m_t_x.py index a690a6e6e..730574733 100644 --- a/Lib/fontTools/ttLib/tables/_h_m_t_x.py +++ b/Lib/fontTools/ttLib/tables/_h_m_t_x.py @@ -1,5 +1,5 @@ from fontTools.misc.py23 import * -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools import ttLib from fontTools.misc.textTools import safeEval from . import DefaultTable diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py index 008909bdd..a65ec7b87 100644 --- a/Lib/fontTools/ttLib/tables/otTables.py +++ b/Lib/fontTools/ttLib/tables/otTables.py @@ -9,7 +9,7 @@ from enum import IntEnum import itertools from collections import namedtuple from fontTools.misc.py23 import * -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import otRound from fontTools.misc.textTools import pad, safeEval from .otBase import ( BaseTable, FormatSwitchingBaseTable, ValueRecord, CountReference, diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py index dd320b040..995159bcd 100644 --- a/Lib/fontTools/varLib/__init__.py +++ b/Lib/fontTools/varLib/__init__.py @@ -19,7 +19,7 @@ Then you can make a variable-font this way: API *will* change in near future. """ from fontTools.misc.py23 import * -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import noRound, otRound from fontTools.misc.vector import Vector from fontTools.ttLib import TTFont, newTable from fontTools.ttLib.tables._f_v_a_r import Axis, NamedInstance @@ -34,6 +34,7 @@ from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib.iup import iup_delta_optimize from fontTools.varLib.featureVars import addFeatureVariations from fontTools.designspaceLib import DesignSpaceDocument +from functools import partial from collections import OrderedDict, namedtuple import os.path import logging @@ -253,7 +254,7 @@ def _add_gvar(font, masterModel, master_ttfs, tolerance=0.5, optimize=True): # Update gvar gvar.variations[glyph] = [] - deltas = model.getDeltas(allCoords) + deltas = model.getDeltas(allCoords, round=partial(GlyphCoordinates.__round__, round=round)) supports = model.supports assert len(deltas) == len(supports) @@ -262,7 +263,7 @@ def _add_gvar(font, masterModel, master_ttfs, tolerance=0.5, optimize=True): endPts = control.endPts for i,(delta,support) in enumerate(zip(deltas[1:], supports[1:])): - if all(abs(v) <= tolerance for v in delta.array) and not isComposite: + if all(v == 0 for v in delta.array) and not isComposite: continue var = TupleVariation(support, delta) if optimize: @@ -304,7 +305,7 @@ def _remove_TTHinting(font): font["glyf"].removeHinting() # TODO: Modify gasp table to deactivate gridfitting for all ranges? -def _merge_TTHinting(font, masterModel, master_ttfs, tolerance=0.5): +def _merge_TTHinting(font, masterModel, master_ttfs): log.info("Merging TT hinting") assert "cvar" not in font @@ -363,10 +364,9 @@ def _merge_TTHinting(font, masterModel, master_ttfs, tolerance=0.5): return variations = [] - deltas, supports = masterModel.getDeltasAndSupports(all_cvs) + deltas, supports = masterModel.getDeltasAndSupports(all_cvs, round=round) # builtin round calls into Vector.__round__, which uses builtin round as we like for i,(delta,support) in enumerate(zip(deltas[1:], supports[1:])): - delta = [otRound(d) for d in delta] - if all(abs(v) <= tolerance for v in delta): + if all(v == 0 for v in delta): continue var = TupleVariation(support, delta) variations.append(var) @@ -441,7 +441,7 @@ def _get_advance_metrics(font, masterModel, master_ttfs, vOrigDeltasAndSupports = {} for glyph in glyphOrder: vhAdvances = [metrics[glyph][0] if glyph in metrics else None for metrics in advMetricses] - vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vhAdvances) + vhAdvanceDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vhAdvances, round=round) singleModel = models.allEqual(id(v[1]) for v in vhAdvanceDeltasAndSupports.values()) @@ -453,7 +453,7 @@ def _get_advance_metrics(font, masterModel, master_ttfs, # glyphs which have a non-default vOrig. vOrigs = [metrics[glyph] if glyph in metrics else defaultVOrig for metrics, defaultVOrig in vOrigMetricses] - vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vOrigs) + vOrigDeltasAndSupports[glyph] = masterModel.getDeltasAndSupports(vOrigs, round=round) directStore = None if singleModel: @@ -463,7 +463,7 @@ def _get_advance_metrics(font, masterModel, master_ttfs, varTupleIndexes = list(range(len(supports))) varData = builder.buildVarData(varTupleIndexes, [], optimize=False) for glyphName in glyphOrder: - varData.addItem(vhAdvanceDeltasAndSupports[glyphName][0]) + varData.addItem(vhAdvanceDeltasAndSupports[glyphName][0], round=noRound) varData.optimize() directStore = builder.buildVarStore(varTupleList, [varData]) @@ -473,14 +473,14 @@ def _get_advance_metrics(font, masterModel, master_ttfs, for glyphName in glyphOrder: deltas, supports = vhAdvanceDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) - advMapping[glyphName] = storeBuilder.storeDeltas(deltas) + advMapping[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound) if vOrigMetricses: vOrigMap = {} for glyphName in glyphOrder: deltas, supports = vOrigDeltasAndSupports[glyphName] storeBuilder.setSupports(supports) - vOrigMap[glyphName] = storeBuilder.storeDeltas(deltas) + vOrigMap[glyphName] = storeBuilder.storeDeltas(deltas, round=noRound) indirectStore = storeBuilder.finish() mapping2 = indirectStore.optimize() diff --git a/Lib/fontTools/varLib/cff.py b/Lib/fontTools/varLib/cff.py index 0a6ba220b..db1889888 100644 --- a/Lib/fontTools/varLib/cff.py +++ b/Lib/fontTools/varLib/cff.py @@ -17,8 +17,10 @@ from fontTools.cffLib.specializer import ( from fontTools.ttLib import newTable from fontTools import varLib from fontTools.varLib.models import allEqual +from fontTools.misc.roundTools import roundFunc from fontTools.misc.psCharStrings import T2CharString, T2OutlineExtractor -from fontTools.pens.t2CharStringPen import T2CharStringPen, t2c_round +from fontTools.pens.t2CharStringPen import T2CharStringPen +from functools import partial from .errors import VarLibCFFDictMergeError, VarLibCFFPointTypeMergeError, VarLibMergeError @@ -422,16 +424,6 @@ def merge_charstrings(glyphOrder, num_masters, top_dicts, masterModel): return cvData -def makeRoundNumberFunc(tolerance): - if tolerance < 0: - raise ValueError("Rounding tolerance must be positive") - - def roundNumber(val): - return t2c_round(val, tolerance) - - return roundNumber - - class CFFToCFF2OutlineExtractor(T2OutlineExtractor): """ This class is used to remove the initial width from the CFF charstring without trying to add the width to self.nominalWidthX, @@ -518,7 +510,7 @@ class CFF2CharStringMergePen(T2CharStringPen): self.prev_move_idx = 0 self.seen_moveto = False self.glyphName = glyphName - self.roundNumber = makeRoundNumberFunc(roundTolerance) + self.round = roundFunc(roundTolerance, round=round) def add_point(self, point_type, pt_coords): if self.m_index == 0: @@ -594,7 +586,7 @@ class CFF2CharStringMergePen(T2CharStringPen): def getCommands(self): return self._commands - def reorder_blend_args(self, commands, get_delta_func, round_func): + def reorder_blend_args(self, commands, get_delta_func): """ We first re-order the master coordinate values. For a moveto to lineto, the args are now arranged as: @@ -637,8 +629,6 @@ class CFF2CharStringMergePen(T2CharStringPen): else: # convert to deltas deltas = get_delta_func(coord)[1:] - if round_func: - deltas = [round_func(delta) for delta in deltas] coord = [coord[0]] + deltas new_coords.append(coord) cmd[1] = new_coords @@ -649,8 +639,7 @@ class CFF2CharStringMergePen(T2CharStringPen): self, private=None, globalSubrs=None, var_model=None, optimize=True): commands = self._commands - commands = self.reorder_blend_args(commands, var_model.getDeltas, - self.roundNumber) + commands = self.reorder_blend_args(commands, partial (var_model.getDeltas, round=self.round)) if optimize: commands = specializeCommands( commands, generalizeFirst=False, diff --git a/Lib/fontTools/varLib/merger.py b/Lib/fontTools/varLib/merger.py index 071942b86..cb53f04d3 100644 --- a/Lib/fontTools/varLib/merger.py +++ b/Lib/fontTools/varLib/merger.py @@ -3,8 +3,8 @@ Merge OpenType Layout tables (GDEF / GPOS / GSUB). """ import copy from operator import ior -from fontTools.misc.fixedTools import otRound from fontTools.misc import classifyTools +from fontTools.misc.roundTools import otRound from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables import otBase as otBase from fontTools.ttLib.tables.DefaultTable import DefaultTable diff --git a/Lib/fontTools/varLib/models.py b/Lib/fontTools/varLib/models.py index 2a484529f..9296dedac 100644 --- a/Lib/fontTools/varLib/models.py +++ b/Lib/fontTools/varLib/models.py @@ -5,6 +5,7 @@ __all__ = ['nonNone', 'allNone', 'allEqual', 'allEqualTo', 'subList', 'supportScalar', 'VariationModel'] +from fontTools.misc.roundTools import noRound from .errors import VariationModelError @@ -367,7 +368,7 @@ class VariationModel(object): deltaWeights.append(deltaWeight) self.deltaWeights = deltaWeights - def getDeltas(self, masterValues): + def getDeltas(self, masterValues, *, round=noRound): assert len(masterValues) == len(self.deltaWeights) mapping = self.reverseMapping out = [] @@ -375,12 +376,12 @@ class VariationModel(object): delta = masterValues[mapping[i]] for j,weight in weights.items(): delta -= out[j] * weight - out.append(delta) + out.append(round(delta)) return out - def getDeltasAndSupports(self, items): + def getDeltasAndSupports(self, items, *, round=noRound): model, items = self.getSubModel(items) - return model.getDeltas(items), model.supports + return model.getDeltas(items, round=round), model.supports def getScalars(self, loc): return [supportScalar(loc, support) for support in self.supports] @@ -402,12 +403,12 @@ class VariationModel(object): scalars = self.getScalars(loc) return self.interpolateFromDeltasAndScalars(deltas, scalars) - def interpolateFromMasters(self, loc, masterValues): - deltas = self.getDeltas(masterValues) + def interpolateFromMasters(self, loc, masterValues, *, round=noRound): + deltas = self.getDeltas(masterValues, round=round) return self.interpolateFromDeltas(loc, deltas) - def interpolateFromMastersAndScalars(self, masterValues, scalars): - deltas = self.getDeltas(masterValues) + def interpolateFromMastersAndScalars(self, masterValues, scalars, *, round=noRound): + deltas = self.getDeltas(masterValues, round=round) return self.interpolateFromDeltasAndScalars(deltas, scalars) diff --git a/Lib/fontTools/varLib/mutator.py b/Lib/fontTools/varLib/mutator.py index 39755ad02..02ce44223 100644 --- a/Lib/fontTools/varLib/mutator.py +++ b/Lib/fontTools/varLib/mutator.py @@ -3,7 +3,8 @@ Instantiate a variation font. Run, eg: $ fonttools varLib.mutator ./NotoSansArabic-VF.ttf wght=140 wdth=85 """ -from fontTools.misc.fixedTools import floatToFixedToFloat, otRound, floatToFixed +from fontTools.misc.fixedTools import floatToFixedToFloat, floatToFixed +from fontTools.misc.roundTools import otRound from fontTools.pens.boundsPen import BoundsPen from fontTools.ttLib import TTFont, newTable from fontTools.ttLib.tables import ttProgram diff --git a/Lib/fontTools/varLib/plot.py b/Lib/fontTools/varLib/plot.py index b6561dc6a..811559fa6 100644 --- a/Lib/fontTools/varLib/plot.py +++ b/Lib/fontTools/varLib/plot.py @@ -2,8 +2,8 @@ from fontTools.varLib.models import VariationModel, supportScalar from fontTools.designspaceLib import DesignSpaceDocument -from mpl_toolkits.mplot3d import axes3d from matplotlib import pyplot +from mpl_toolkits.mplot3d import axes3d from itertools import cycle import math import logging @@ -68,10 +68,10 @@ def plotLocations(locations, fig, names=None, **kwargs): def _plotLocations2D(model, axis, fig, cols, rows, names, **kwargs): + subplot = fig.add_subplot(111) for i, (support, color, name) in enumerate( zip(model.supports, cycle(pyplot.cm.Set1.colors), cycle(names)) ): - subplot = fig.add_subplot(rows, cols, i + 1) if name is not None: subplot.set_title(name) subplot.set_xlabel(axis) @@ -91,10 +91,10 @@ def _plotLocations2D(model, axis, fig, cols, rows, names, **kwargs): def _plotLocations3D(model, axes, fig, rows, cols, names, **kwargs): ax1, ax2 = axes + axis3D = fig.add_subplot(111, projection='3d') for i, (support, color, name) in enumerate( zip(model.supports, cycle(pyplot.cm.Set1.colors), cycle(names)) ): - axis3D = fig.add_subplot(rows, cols, i + 1, projection='3d') if name is not None: axis3D.set_title(name) axis3D.set_xlabel(ax1) diff --git a/Lib/fontTools/varLib/varStore.py b/Lib/fontTools/varLib/varStore.py index b28d2a657..8a382df01 100644 --- a/Lib/fontTools/varLib/varStore.py +++ b/Lib/fontTools/varLib/varStore.py @@ -1,4 +1,4 @@ -from fontTools.misc.fixedTools import otRound +from fontTools.misc.roundTools import noRound, otRound from fontTools.ttLib.tables import otTables as ot from fontTools.varLib.models import supportScalar from fontTools.varLib.builder import (buildVarRegionList, buildVarStore, @@ -83,15 +83,12 @@ class OnlineVarStoreBuilder(object): def storeMasters(self, master_values): - deltas = self._model.getDeltas(master_values) - base = otRound(deltas.pop(0)) - return base, self.storeDeltas(deltas) + deltas = self._model.getDeltas(master_values, round=round) + base = deltas.pop(0) + return base, self.storeDeltas(deltas, round=noRound) - def storeDeltas(self, deltas): - # Pity that this exists here, since VarData_addItem - # does the same. But to look into our cache, it's - # good to adjust deltas here as well... - deltas = [otRound(d) for d in deltas] + def storeDeltas(self, deltas, *, round=round): + deltas = [round(d) for d in deltas] if len(deltas) == len(self._supports) + 1: deltas = tuple(deltas[1:]) else: @@ -109,14 +106,14 @@ class OnlineVarStoreBuilder(object): # Full array. Start new one. self._add_VarData() return self.storeDeltas(deltas) - self._data.addItem(deltas) + self._data.addItem(deltas, round=noRound) varIdx = (self._outer << 16) + inner self._cache[deltas] = varIdx return varIdx -def VarData_addItem(self, deltas): - deltas = [otRound(d) for d in deltas] +def VarData_addItem(self, deltas, *, round=round): + deltas = [round(d) for d in deltas] countUs = self.VarRegionCount countThem = len(deltas) diff --git a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx index f05f62f74..5bbd925c7 100644 --- a/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx +++ b/Tests/varLib/data/test_results/TestSparseCFF2VF.ttx @@ -290,7 +290,7 @@ 2 vsindex - -60 30 203 30 -9 9 67 7 -7 14 -14 30 -20 20 80 30 59 30 121 30 18 93 -30 30 -30 108 -23 0 -26 67 2 76 -98 -2 -111 42 0 47 -13 0 -14 13 0 14 -33 0 -37 11 0 13 -11 0 -13 8 0 9 -7 0 -8 53 0 60 -32 0 -36 32 0 36 -52 0 -59 57 1 65 -33 0 -38 53 0 60 -83 -1 -93 54 0 60 -6 -19 -24 33 19 55 -76 -1 -86 76 1 86 -76 -1 -86 59 1 67 26 blend + -60 30 203 30 -9 9 67 7 -7 14 -14 30 -20 20 80 30 59 30 121 30 18 93 -30 30 -30 108 -23 0 -26 67 2 76 -98 -2 -111 42 0 47 -13 0 -14 13 0 14 -33 0 -37 11 0 13 -11 0 -13 8 0 8 -8 0 -8 53 0 60 -32 0 -36 32 0 36 -52 0 -59 57 1 65 -33 0 -38 53 0 60 -83 -1 -93 54 0 60 -6 -19 -24 33 19 55 -76 -1 -86 76 1 86 -76 -1 -86 59 1 67 26 blend hstemhm 77 30 42 30 139 30 23 30 71 10 74 30 15 30 16 30 158 30 28 30 -4 29 -14 0 -16 88 1 99 -82 -1 -92 87 1 98 -130 -1 -146 102 1 114 -73 -1 -82 74 2 84 -112 -2 -126 27 0 30 13 0 15 90 1 101 -126 -1 -142 75 1 84 -68 -1 -76 102 1 115 -144 -1 -162 94 1 105 -79 -1 -88 95 1 106 -81 -1 -91 74 1 83 22 blend vstemhm