Exemple #1
0
 def _load_fontfile(self):
     try:
         if self.fontfile.endswith(".ufo") or self.fontfile.endswith("tf"):
             # Single master workflow
             self.font = Babelfont.open(self.fontfile)
             self.variations = None
         else:
             self.variations = VariableFont(self.fontfile)
             # We need a "scratch copy" because we will be trashing the
             # glyph data with our interpolations
             if len(self.variations.masters.keys()) == 1:
                 self.font = list(self.variations.masters.values())[0]
                 self.variations = None
             else:
                 firstmaster = self.variations.designspace.sources[0].path
                 if firstmaster:
                     self.font = Babelfont.open(firstmaster)
                 else:  # Glyphs, fontlab?
                     self.font = Babelfont.open(self.fontfile)
     except Exception as e:
         if self.editor:
             self.editor.showError("Couldn't open %s: %s" %
                                   (self.fontfile, e))
         else:
             raise e
         return False
     return True
Exemple #2
0
 def load_masters(self):
     if self.masters:
         return
     for src in self.config["sources"]:
         if src.endswith("glyphs"):
             gsfont = glyphsLib.GSFont(src)
             self.masters[src] = []
             for master in gsfont.masters:
                 self.masters[src].append(
                     Babelfont.open(src, master=master.name))
         elif src.endswith("designspace"):
             continue
         else:
             self.masters[src] = [Babelfont.open(src)]
Exemple #3
0
def test_namedclass_in_slot():
    font = Babelfont.load("tests/data/LibertinusSans-Regular.otf")
    buf = Buffer(font, glyphs=["A", "B", "C"])
    r = Routine()
    r.addRule(Substitution([["G", "@AB"]], [["X"]]))
    r.apply_to_buffer(buf, namedclasses={"AB": ["A", "B"]})
    assert buf.serialize(position=False) == "X|X|C"
Exemple #4
0
def test_double_application():
    font = Babelfont.load(
        "tests/data/acbe26ce904463c690fb67f70679447059d13ee4.otf")
    buf = Buffer(font, glyphs=["dvKA", "dvVirama", "dvKA", "dvVirama", "dvKA"])
    rule = Substitution([["dvKA"], ["dvVirama"]], [["dvK"]])
    rule.apply_to_buffer(buf)
    assert buf.serialize(position=False) == "dvK|dvK|dvKA"
Exemple #5
0
    def test_parse_to_ff(self):
        p = FeeParser(Babelfont.load("fonts/Roboto-Regular.ttf"))
        p.parseString("""
      Anchors A {
        top <679 1600>
        bottom <691 0>
      };

      Anchors B {
        top <611 1612>
      };

      Anchors acutecomb { _top <-570 1290> };
      Anchors tildecomb { _top <-542 1256> };

      Feature mark { Attach &top &_top bases; };
""")

        self.assertEqual(p.fontfeatures.anchors["A"]["top"], (679, 1600))
        self.assertSufficientlyEqual(
            p.fontfeatures.asFea(),
            """    markClass acutecomb <anchor -570 1290> @top;
    markClass tildecomb <anchor -542 1256> @top;


feature mark {  lookup Routine_1 { ;
                        pos base A <anchor 679 1600> mark @top;
            pos base B <anchor 611 1612> mark @top;

} Routine_1;
} mark;
""",
        )
Exemple #6
0
def test_multiple_applications():
    font = Babelfont.load("tests/data/LibertinusSans-Regular.otf")
    buf = Buffer(font, glyphs=["A", "B", "C"])
    r = Routine()
    r.addRule(Substitution([["A"]], [["X"]]))
    r.addRule(Substitution([["B"]], [["Y"]]))
    r.apply_to_buffer(buf)
    assert buf.serialize(position=False) == "X|Y|C"
Exemple #7
0
def test_roundtrip():
    if sys.platform != "darwin":
        pytest.skip("Needs to be run on OS X")
    font = Babelfont.open("tests/data/Test1.glyphs")
    Babelfont.save(font, "tests/data/Test1.roundtrip.glyphs")
    pl1_json = subprocess.run(
        ["plutil", "-convert", "xml1", "-o", "-", "tests/data/Test1.glyphs"],
        capture_output=True,
    )
    pl2_json = subprocess.run(
        [
            "plutil", "-convert", "xml1", "-o", "-",
            "tests/data/Test1.roundtrip.glyphs"
        ],
        capture_output=True,
    )
    pl1 = plistlib.load(BytesIO(pl1_json.stdout))
    pl2 = plistlib.load(BytesIO(pl2_json.stdout))
    assert pl1 == pl2
Exemple #8
0
def test_shaping(request, fontname, hb_args, input_string, expectation):
    font = TTFont(fontname)
    ff = unparse(font)
    bbf = Babelfont.load(fontname)
    if not bbf:
        return pytest.skip("Font too busted to use")
    buf = Buffer(bbf, unicodes=tounicode(input_string))
    shaper = Shaper(ff, bbf)
    feature_string = ""
    if "[" in hb_args:
        return pytest.skip("Partial application not supported yet")

    if "variations" in hb_args:
        return pytest.skip("Not planning to support variations")
    if "ttb" in hb_args:
        return pytest.skip("Not planning to support top-to-bottom")

    if "rand" in request.node.name:
        return pytest.skip("Not planning to support rand feature")
    if "aat" in request.node.name:
        return pytest.skip("Not planning to support Apple Advanced Typography")
    if "kern-format2" in request.node.name:
        return pytest.skip("Not planning to support kern table")
    if "fraction" in request.node.name:
        return pytest.skip("Not planning to support automatic fractions")

    m = re.search(r'--features="([^"]+)"', hb_args)
    if m:
        feature_string = m[1]

    if "--script" in hb_args:
        m = re.search(r"--script=(\w+)", hb_args)
        buf.script = script_map[m[1]]

    shaper.execute(buf, features=feature_string)
    serialize_options = {}
    if "--no-glyph-names" in hb_args:
        serialize_options["names"] = False
    if "--ned" in hb_args:
        serialize_options["ned"] = True
    if "--no-position" in hb_args:
        serialize_options["position"] = False
    if "post" not in font or font["post"].formatType != 2.0:
        serialize_options["names"] = False
        expectation = re.sub("gid", "", expectation)
    serialized = buf.serialize(**serialize_options)

    # Finesse cluster information
    serialized = re.sub(r"=\d+", "", serialized)
    expectation = re.sub(r"=\d+", "", expectation)
    assert "[" + serialized + "]" == expectation
Exemple #9
0
def test_load():
    font = Babelfont.load("tests/data/NewFont-Regular.ttf")
    a_layer = font["A"]
    assert isinstance(a_layer, Glyph)
    assert len(a_layer.contours) == 2
    assert len(a_layer.contours[0].points) == 8
    assert len(a_layer.contours[1].points) == 4
    assert a_layer.contours[0].points[0].x == 345
    assert a_layer.contours[0].points[0].y == 700
    assert a_layer.leftMargin == 25
    assert a_layer.rightMargin == 25
    assert a_layer.bounds == (25, 0, 505, 700)
    assert a_layer.width == 530

    dot = font["uni0307"]
    assert dot.category == "mark"
    assert font.glyphForCodepoint(ord("A")) == "A"
Exemple #10
0
def main():
    parser = argparse.ArgumentParser(
        prog="babelfont", description='Convert between font formats')
    parser.add_argument('input', metavar='IN', help="Input file")
    parser.add_argument('output', metavar='OUT', help="Output file")
    args = parser.parse_args()

    try:
        font = Babelfont.load(args.input)
    except Exception as e:
        print("Couldn't read %s: %s" % (args.input, e))
        sys.exit(1)

    try:
        font.save(args.output)
    except Exception as e:
        print("Couldn't write %s: %s" % (args.output, e))
        raise e
        sys.exit(1)

    sys.exit(0)
Exemple #11
0
class TestFeeDefinitions(unittest.TestCase):
    roboto = FeeParser(Babelfont.load("fonts/Roboto-Regular.ttf"))

    def assertSufficientlyEqual(self, s1, s2):
        def alltrim(a):
            a = re.sub("#.*", "", a)
            a = re.sub("\\s+", " ", a)
            return a.strip()

        self.assertEqual(alltrim(s1), alltrim(s2))

    def test_parse_to_ff(self):
        self.roboto.parseString("""
        	DefineClass @vowels = /^[aeiou]$/;
        	DefineClass @consonants = /^[bcdfghjklmnpqrstvwxyz]$/;
        	DefineClass @letters = [@vowels @consonants];
        	""")
        self.assertEqual(len(self.roboto.fontfeatures.namedClasses["letters"]),
                         26)

    def test_unicode_range_selector(self):
        self.roboto.parseString("DefineClass @digits = U+0030=>U+0039;")
        self.assertEqual(len(self.roboto.fontfeatures.namedClasses["digits"]),
                         10)
Exemple #12
0
def test_ufo_roundtrip():
    font = Babelfont.open("tests/data/Test1.ufo")
    Babelfont.save(font, "tests/data/Test1.roundtrip.ufo")
    dc1 = defcon.Font("tests/data/Test1.ufo")
    dc2 = defcon.Font("tests/data/Test1.roundtrip.ufo")
    assert dc1.getDataForSerialization() == dc2.getDataForSerialization()
Exemple #13
0
def test_ufo_load():
    font = Babelfont.open("tests/data/Test1.ufo")
    assert font.glyphForCodepoint(ord("A")) == "A"
Exemple #14
0
def test_loader():
    filename = "tests/data/Castoro Roman.vfj"
    font = Babelfont.open(filename)
def parser():
    path, _ = os.path.split(__file__)
    fontpath = os.path.join(path, "data", "LibertinusSans-Regular.otf")
    return FeeParser(Babelfont.load(fontpath))
Exemple #16
0
 def _save(self, path=None, **kwargs):
     if not path:
         path = self._path
     if not path:
         raise ValueError
     Babelfont.save(self, path)
Exemple #17
0
def test_round_trip():
    font = Babelfont.load("tests/data/Nunito-Regular.ttf")
    TTFont("tests/data/Nunito-Regular.ttf").saveXML("tests/data/Nunito-1.ttx")
    font.save("tests/data/Nunito-from-ttf.ttf")
    TTFont("tests/data/Nunito-from-ttf.ttf").saveXML("tests/data/Nunito-2.ttx")
import pytest
import os
import re


def alltrim(a):
    a = re.sub("lookupflag 0;", "", a)
    a = re.sub("#.*", "", a)
    a = re.sub("\\s+", " ", a)
    a = re.sub("table GDEF.*GDEF;", "", a)
    return a.strip()


path, _ = os.path.split(__file__)
fontpath = os.path.join(path, "data", "LibertinusSans-Regular.otf")
font = Babelfont.load(fontpath)


@pytest.fixture
def parser():
    return FeeParser(font)


############
# BareName #
############


class BareNameModule:
    GRAMMAR = """
    ?start: action
Exemple #19
0
def test_ufo_to_glyphs():
    font = Babelfont.open("tests/data/Test1.ufo")
    Babelfont.save(font, "tests/data/Test1-from-ufo.glyphs")
Exemple #20
0
def test_otfloader(fontname):
    font = Babelfont.load(fontname)
Exemple #21
0
def test_load_glyph():
    filename = "tests/data/Castoro Roman.vfj"
    font = Babelfont.open(filename)

    assert len(font["A"].contours[0]) == 20
    assert len(font["A"].contours[1]) == 4
Exemple #22
0
def test_glyphs_to_ufo():
    font = Babelfont.open("tests/data/Test1.glyphs")
    Babelfont.save(font, "tests/data/Test1-from-glyphs.ufo")