Esempio n. 1
0
def AddGlyphVariations(font, thin, regular, black):
    assert "gvar" not in font
    gvar = font["gvar"] = table__g_v_a_r()
    gvar.version = 1
    gvar.reserved = 0
    gvar.variations = {}
    for glyphName in regular.getGlyphOrder():
        regularCoord = GetCoordinates(regular, glyphName)
        thinCoord = GetCoordinates(thin, glyphName)
        blackCoord = GetCoordinates(black, glyphName)
        if not regularCoord or not blackCoord or not thinCoord:
            logging.warning("glyph %s not present in all input fonts",
                            glyphName)
            continue
        if (len(regularCoord) != len(blackCoord)
                or len(regularCoord) != len(thinCoord)):
            logging.warning(
                "glyph %s has not the same number of "
                "control points in all input fonts", glyphName)
            continue
        thinDelta = []
        blackDelta = []
        for ((regX, regY), (blackX, blackY), (thinX, thinY)) in \
                zip(regularCoord, blackCoord, thinCoord):
            thinDelta.append(((thinX - regX, thinY - regY)))
            blackDelta.append((blackX - regX, blackY - regY))
        thinVar = GlyphVariation({"wght": (-1.0, -1.0, 0.0)}, thinDelta)
        blackVar = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, blackDelta)
        gvar.variations[glyphName] = [thinVar, blackVar]
Esempio n. 2
0
 def test_compileGlyph_onlyRedundantVariations(self):
     table = table__g_v_a_r()
     axes = {"wght": (0.3, 0.4, 0.5), "opsz": (0.7, 0.8, 0.9)}
     table.variations = {
         "glyphname": [
             GlyphVariation(axes, [None] * 4),
             GlyphVariation(axes, [None] * 4),
             GlyphVariation(axes, [None] * 4)
         ]
     }
     self.assertEqual(
         b"", table.compileGlyph_("glyphname", 8, ["wght", "opsz"], {}))
Esempio n. 3
0
def _add_gvar(font, model, master_ttfs):

    print("Generating gvar")
    assert "gvar" not in font
    gvar = font["gvar"] = newTable('gvar')
    gvar.version = 1
    gvar.reserved = 0
    gvar.variations = {}

    for glyph in font.getGlyphOrder():

        allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
        allCoords = [d[0] for d in allData]
        allControls = [d[1] for d in allData]
        control = allControls[0]
        if (any(c != control for c in allControls)):
            warnings.warn("glyph %s has incompatible masters; skipping" %
                          glyph)
            continue
        del allControls

        # Update gvar
        gvar.variations[glyph] = []
        deltas = model.getDeltas(allCoords)
        supports = model.supports
        assert len(deltas) == len(supports)
        for i, (delta, support) in enumerate(zip(deltas[1:], supports[1:])):
            var = GlyphVariation(support, delta)
            gvar.variations[glyph].append(var)
Esempio n. 4
0
 def test_decompileCoord_roundTrip(self):
     # Make sure we are not affected by https://github.com/behdad/fonttools/issues/286
     data = deHexStr("7F B9 80 35")
     values, _ = GlyphVariation.decompileCoord_(["wght", "wdth"], data, 0)
     axisValues = {axis: (val, val, val) for axis, val in values.items()}
     gvar = GlyphVariation(axisValues, [None] * 4)
     self.assertEqual("7F B9 80 35",
                      hexencode(gvar.compileCoord(["wght", "wdth"])))
Esempio n. 5
0
def _add_gvar(font, axes, master_ttfs, master_locs, base_idx):

    # Make copies for modification
    master_ttfs = master_ttfs[:]
    master_locs = [l.copy() for l in master_locs]

    axis_tags = axes.keys()

    # Normalize master locations. TODO Move to a separate function.
    for tag, (name, lower, default, upper) in axes.items():
        for l in master_locs:
            v = l[tag]
            if v == default:
                v = 0
            elif v < default:
                v = (v - default) / (default - lower)
            else:
                v = (v - default) / (upper - default)
            l[tag] = v
    # Locations are normalized now

    print("Normalized master positions:")
    print(master_locs)

    print("Generating gvar")
    assert "gvar" not in font
    gvar = font["gvar"] = table__g_v_a_r()
    gvar.version = 1
    gvar.reserved = 0
    gvar.variations = {}

    # Assume single-model for now.
    model = VariationModel(master_locs)
    model_base_idx = model.mapping[base_idx]
    assert 0 == model_base_idx

    for glyph in font.getGlyphOrder():

        allData = [_GetCoordinates(m, glyph) for m in master_ttfs]
        allCoords = [d[0] for d in allData]
        allControls = [d[1] for d in allData]
        control = allControls[0]
        if (any(c != control for c in allControls)):
            warnings.warn("glyph %s has incompatible masters; skipping" %
                          glyph)
            continue
        del allControls

        gvar.variations[glyph] = []

        deltas = model.getDeltas(allCoords)
        supports = model.supports
        assert len(deltas) == len(supports)
        for i, (delta, support) in enumerate(zip(deltas, supports)):
            if i == model_base_idx:
                continue
            var = GlyphVariation(support, delta)
            gvar.variations[glyph].append(var)
Esempio n. 6
0
 def test_toXML_allDeltasNone(self):
     writer = XMLWriter(BytesIO())
     axes = {"wght": (0.0, 1.0, 1.0)}
     g = GlyphVariation(axes, [None] * 5)
     g.toXML(writer, ["wght", "wdth"])
     self.assertEqual([
         '<tuple>', '<coord axis="wght" value="1.0"/>',
         '<!-- no deltas -->', '</tuple>'
     ], GlyphVariationTest.xml_lines(writer))
Esempio n. 7
0
 def test_compileCoord(self):
     gvar = GlyphVariation(
         {
             "wght": (-1.0, -1.0, -1.0),
             "wdth": (0.4, 0.5, 0.6)
         }, [None] * 4)
     self.assertEqual("C0 00 20 00",
                      hexencode(gvar.compileCoord(["wght", "wdth"])))
     self.assertEqual("20 00 C0 00",
                      hexencode(gvar.compileCoord(["wdth", "wght"])))
     self.assertEqual("C0 00", hexencode(gvar.compileCoord(["wght"])))
Esempio n. 8
0
 def test_compileGlyph_roundTrip(self):
     table = table__g_v_a_r()
     axisTags = ["wght", "wdth"]
     numPointsInGlyph = 4
     glyphCoords = [(1, 1), (2, 2), (3, 3), (4, 4)]
     gvar1 = GlyphVariation(
         {
             "wght": (0.5, 1.0, 1.0),
             "wdth": (1.0, 1.0, 1.0)
         }, glyphCoords)
     gvar2 = GlyphVariation(
         {
             "wght": (1.0, 1.0, 1.0),
             "wdth": (1.0, 1.0, 1.0)
         }, glyphCoords)
     table.variations = {"oslash": [gvar1, gvar2]}
     data = table.compileGlyph_("oslash", numPointsInGlyph, axisTags, {})
     self.assertEqual([gvar1, gvar2],
                      table.decompileGlyph_(numPointsInGlyph, {}, axisTags,
                                            data))
Esempio n. 9
0
 def test_compileIntermediateCoord(self):
     gvar = GlyphVariation(
         {
             "wght": (-1.0, -1.0, 0.0),
             "wdth": (0.4, 0.5, 0.6)
         }, [None] * 4)
     self.assertEqual(
         "C0 00 19 9A 00 00 26 66",
         hexencode(gvar.compileIntermediateCoord(["wght", "wdth"])))
     self.assertEqual(
         "19 9A C0 00 26 66 00 00",
         hexencode(gvar.compileIntermediateCoord(["wdth", "wght"])))
     self.assertEqual(None, gvar.compileIntermediateCoord(["wght"]))
     self.assertEqual("19 9A 26 66",
                      hexencode(gvar.compileIntermediateCoord(["wdth"])))
Esempio n. 10
0
 def test_fromXML(self):
     g = GlyphVariation({}, [None] * 4)
     for name, attrs, content in parseXML(
             '<coord axis="wdth" min="0.3" value="0.4" max="0.5"/>'
             '<coord axis="wght" value="1.0"/>'
             '<coord axis="opsz" value="-0.5"/>'
             '<delta pt="1" x="33" y="44"/>'
             '<delta pt="2" x="-2" y="170"/>'):
         g.fromXML(name, attrs, content)
     self.assertEqual(
         {
             "wdth": (0.3, 0.4, 0.5),
             "wght": (0.0, 1.0, 1.0),
             "opsz": (-0.5, -0.5, 0.0)
         }, g.axes)
     self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
Esempio n. 11
0
 def test_compile_embeddedCoords_nonIntermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices={},
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=EMBEDDED_TUPLE_COORD
     # embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[]
     self.assertEqual("00 08 80 00 20 00 33 33", hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Esempio n. 12
0
 def test_toXML(self):
     writer = XMLWriter(BytesIO())
     axes = {
         "wdth": (0.3, 0.4, 0.5),
         "wght": (0.0, 1.0, 1.0),
         "opsz": (-0.7, -0.7, 0.0)
     }
     g = GlyphVariation(axes, [(9, 8), None, (7, 6), (0, 0),
                               (-1, -2), None])
     g.toXML(writer, ["wdth", "wght", "opsz"])
     self.assertEqual([
         '<tuple>', '<coord axis="wdth" max="0.5" min="0.3" value="0.4"/>',
         '<coord axis="wght" value="1.0"/>',
         '<coord axis="opsz" value="-0.7"/>', '<delta pt="0" x="9" y="8"/>',
         '<delta pt="2" x="7" y="6"/>', '<delta pt="3" x="0" y="0"/>',
         '<delta pt="4" x="-1" y="-2"/>', '</tuple>'
     ], GlyphVariationTest.xml_lines(writer))
Esempio n. 13
0
 def test_compile_embeddedCoords_nonIntermediate_privatePoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices={},
                                sharedPoints=None)
     # len(data)=13; flags=PRIVATE_POINT_NUMBERS|EMBEDDED_TUPLE_COORD
     # embeddedCoord=[(0.5, 0.8)]; intermediateCoord=[]
     self.assertEqual("00 09 A0 00 20 00 33 33", hexencode(tuple))
     self.assertEqual(
         "00 "  # all points in glyph
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Esempio n. 14
0
 def test_compile_sharedCoords_nonIntermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 0.5),
             "wdth": (0.0, 0.8, 0.8)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=None; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[]
     self.assertEqual("00 08 00 77", hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Esempio n. 15
0
 def test_compile_sharedCoords_intermediate_sharedPoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.3, 0.5, 0.7),
             "wdth": (0.1, 0.8, 0.9)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints={0, 1, 2})
     # len(data)=8; flags=INTERMEDIATE_TUPLE; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[(0.3, 0.1), (0.7, 0.9)]
     self.assertEqual("00 08 40 77 13 33 06 66 2C CD 39 9A",
                      hexencode(tuple))
     self.assertEqual(
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Esempio n. 16
0
 def test_fromXML(self):
     g = GlyphVariation({}, [None] * 4)
     g.fromXML("coord", {
         "axis": "wdth",
         "min": "0.3",
         "value": "0.4",
         "max": "0.5"
     }, [])
     g.fromXML("coord", {"axis": "wght", "value": "1.0"}, [])
     g.fromXML("coord", {"axis": "opsz", "value": "-0.5"}, [])
     g.fromXML("delta", {"pt": "1", "x": "33", "y": "44"}, [])
     g.fromXML("delta", {"pt": "2", "x": "-2", "y": "170"}, [])
     self.assertEqual(
         {
             "wdth": (0.3, 0.4, 0.5),
             "wght": (0.0, 1.0, 1.0),
             "opsz": (-0.5, -0.5, 0.0)
         }, g.axes)
     self.assertEqual([None, (33, 44), (-2, 170), None], g.coordinates)
Esempio n. 17
0
 def test_compile_sharedCoords_intermediate_privatePoints(self):
     gvar = GlyphVariation(
         {
             "wght": (0.0, 0.5, 1.0),
             "wdth": (0.0, 0.8, 1.0)
         }, [(7, 4), (8, 5), (9, 6)])
     axisTags = ["wght", "wdth"]
     sharedCoordIndices = {gvar.compileCoord(axisTags): 0x77}
     tuple, data = gvar.compile(axisTags,
                                sharedCoordIndices,
                                sharedPoints=None)
     # len(data)=13; flags=PRIVATE_POINT_NUMBERS; tupleIndex=0x77
     # embeddedCoord=[]; intermediateCoord=[(0.0, 0.0), (1.0, 1.0)]
     self.assertEqual("00 09 60 77 00 00 00 00 40 00 40 00",
                      hexencode(tuple))
     self.assertEqual(
         "00 "  # all points in glyph
         "02 07 08 09 "  # deltaX: [7, 8, 9]
         "02 04 05 06",  # deltaY: [4, 5, 6]
         hexencode(data))
Esempio n. 18
0
 def test_compileSharedCoords(self):
     table = table__g_v_a_r()
     table.variations = {}
     deltas = [None] * 4
     table.variations["A"] = [
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.5, 0.7, 1.0)
         }, deltas)
     ]
     table.variations["B"] = [
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.2, 0.7, 1.0)
         }, deltas),
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.2, 0.8, 1.0)
         }, deltas)
     ]
     table.variations["C"] = [
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.3, 0.7, 1.0)
         }, deltas),
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.3, 0.8, 1.0)
         }, deltas),
         GlyphVariation({
             "wght": (1.0, 1.0, 1.0),
             "wdth": (0.3, 0.9, 1.0)
         }, deltas)
     ]
     # {"wght":1.0, "wdth":0.7} is shared 3 times; {"wght":1.0, "wdth":0.8} is shared twice.
     # Min and max values are not part of the shared coordinate pool and should get ignored.
     result = table.compileSharedCoords_(["wght", "wdth"])
     self.assertEqual(["40 00 2C CD", "40 00 33 33"],
                      [hexencode(c) for c in result])
Esempio n. 19
0
 def test_equal_differentCoordinates(self):
     gvar1 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     gvar2 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8)])
     self.assertNotEqual(gvar1, gvar2)
Esempio n. 20
0
 def test_hasImpact_allDeltasZero(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [(0, 0), (0, 0), (0, 0)])
     self.assertTrue(gvar.hasImpact())
Esempio n. 21
0
 def test_compileDeltas(self):
     gvar = GlyphVariation({}, [(0, 0), (1, 0), (2, 0), (3, 3)])
     points = {1, 2}
     # deltaX for points: [1, 2]; deltaY for points: [0, 0]
     self.assertEqual("01 01 02 81", hexencode(gvar.compileDeltas(points)))
Esempio n. 22
0
 def test_equal(self):
     gvar1 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     gvar2 = GlyphVariation({"wght": (0.0, 1.0, 1.0)}, [(0, 0), (9, 8),
                                                        (7, 6)])
     self.assertEqual(gvar1, gvar2)
Esempio n. 23
0
 def test_hasImpact_allDeltasNone(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [None, None, None])
     self.assertFalse(gvar.hasImpact())
Esempio n. 24
0
 def test_hasImpact_someDeltasNotZero(self):
     axes = {"wght": (0.0, 1.0, 1.0)}
     gvar = GlyphVariation(axes, [(0, 0), (9, 8), (7, 6)])
     self.assertTrue(gvar.hasImpact())