diff --git a/Lib/fontMath/mathKerning.py b/Lib/fontMath/mathKerning.py index dd25bbb..47958cf 100644 --- a/Lib/fontMath/mathKerning.py +++ b/Lib/fontMath/mathKerning.py @@ -19,13 +19,14 @@ class kerning dictionary. class MathKerning(object): - def __init__(self, kerning=None, groups=None): + def __init__(self, kerning=None, groups=None, strictGroups=False): if kerning is None: kerning = {} if groups is None: groups = {} self.update(kerning) self.updateGroups(groups) + self.strictGroups = strictGroups # ------- # Loading @@ -168,6 +169,11 @@ def __sub__(self, other): return k def _processMathOne(self, other, funct): + g1 = self.groups() + g2 = other.groups() + if self.strictGroups or other.strictGroups: + if g1 != g2: + raise ValueError("Kerning groups must be exactly the same.") comboPairs = set(self._kerning.keys()) | set(other._kerning.keys()) kerning = dict.fromkeys(comboPairs, None) for k in comboPairs: @@ -175,8 +181,6 @@ def _processMathOne(self, other, funct): v2 = other.get(k) v = funct(v1, v2) kerning[k] = v - g1 = self.groups() - g2 = other.groups() if g1 == g2 or not g1 or not g2: groups = g1 or g2 else: diff --git a/Lib/fontMath/test/test_mathKerning.py b/Lib/fontMath/test/test_mathKerning.py index e7fdcb0..183fdca 100644 --- a/Lib/fontMath/test/test_mathKerning.py +++ b/Lib/fontMath/test/test_mathKerning.py @@ -115,7 +115,37 @@ def test_copy(self): obj2 = obj1.copy() self.assertEqual(sorted(obj1.items()), sorted(obj2.items())) - def test_add(self): + def test_add_different_groups_strict(self): + kerning1 = { + ("A", "A"): 1, + ("B", "B"): 1, + ("NotIn2", "NotIn2"): 1, + ("public.kern1.NotIn2", "C"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups1 = { + "public.kern1.NotIn1": ["C"], + "public.kern1.D": ["D", "H"], + "public.kern2.D": ["D", "H"], + } + kerning2 = { + ("A", "A"): -1, + ("B", "B"): 1, + ("NotIn1", "NotIn1"): 1, + ("public.kern1.NotIn1", "C"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups2 = { + "public.kern1.NotIn2": ["C"], + "public.kern1.D": ["D", "H"], + "public.kern2.D": ["D", "H"], + } + with self.assertRaises(ValueError): + obj = MathKerning(kerning1, groups1, strictGroups=True) + MathKerning(kerning2, groups2) + with self.assertRaises(ValueError): + obj = MathKerning(kerning1, groups1) + MathKerning(kerning2, groups2, strictGroups=True) + + def test_add_different_groups(self): kerning1 = { ("A", "A"): 1, ("B", "B"): 1, @@ -195,7 +225,37 @@ def test_add_same_groups(self): obj.groups()["public.kern2.D"], ['D', 'H']) - def test_sub(self): + def test_sub_different_groups_strict(self): + kerning1 = { + ("A", "A"): 1, + ("B", "B"): 1, + ("NotIn2", "NotIn2"): 1, + ("public.kern1.NotIn2", "C"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups1 = { + "public.kern1.NotIn1": ["C"], + "public.kern1.D": ["D", "H"], + "public.kern2.D": ["D", "H"], + } + kerning2 = { + ("A", "A"): -1, + ("B", "B"): 1, + ("NotIn1", "NotIn1"): 1, + ("public.kern1.NotIn1", "C"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups2 = { + "public.kern1.NotIn2": ["C"], + "public.kern1.D": ["D"], + "public.kern2.D": ["D", "H"], + } + with self.assertRaises(ValueError): + obj = MathKerning(kerning1, groups1, strictGroups=True) - MathKerning(kerning2, groups2) + with self.assertRaises(ValueError): + obj = MathKerning(kerning1, groups1) - MathKerning(kerning2, groups2, strictGroups=True) + + def test_sub_different_groups(self): kerning1 = { ("A", "A"): 1, ("B", "B"): 1, @@ -235,6 +295,40 @@ def test_sub(self): obj.groups()["public.kern2.D"], ['D', 'H']) + def test_sub_same_groups(self): + kerning1 = { + ("A", "A"): 1, + ("B", "B"): 1, + ("NotIn2", "NotIn2"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups1 = { + "public.kern1.D": ["D", "H"], + "public.kern2.D": ["D", "H"], + } + kerning2 = { + ("A", "A"): -1, + ("B", "B"): 1, + ("NotIn1", "NotIn1"): 1, + ("public.kern1.D", "public.kern2.D"): 1, + } + groups2 = { + "public.kern1.D": ["D"], + "public.kern2.D": ["D", "H"], + } + obj = MathKerning(kerning1, groups1) - MathKerning(kerning2, groups2) + self.assertEqual( + sorted(obj.items()), + [(('A', 'A'), 2), + (('NotIn1', 'NotIn1'), -1), + (('NotIn2', 'NotIn2'), 1)]) + self.assertEqual( + obj.groups()["public.kern1.D"], + ['D', 'H']) + self.assertEqual( + obj.groups()["public.kern2.D"], + ['D', 'H']) + def test_mul(self): kerning = { ("A", "A"): 0,