Example #1
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"
 def test_MergeMultipleSingleSubstitutions_1(self):
     r1 = Routine(rules=[
         Substitution([["a", "y"]], [["b", "z"]]),
         Substitution([["b", "d", "a"]], [["c", "e", "f"]]),
     ])
     Optimizer(FontFeatures()).optimize_routine(r1, level=1)
     self.assertEqual(r1.asFea(), "    sub [a y b d] by [c z c e];\n")
Example #3
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"
Example #4
0
 def test_single(self):
     s = Substitution(["a"], ["b"])
     self.assertEqual(s.asFea(), "sub a by b;")
     self.assertEqual(s.involved_glyphs, set(["a", "b"]))
     self.assertEqual(
         etree.tostring(s.toXML()),
         "<substitution><from><slot><glyph>a</glyph></slot></from><to><slot><glyph>b</glyph></slot></to></substitution>"
         .encode("utf-8"))
     self.roundTrip(s)
 def test_MergeMultipleSingleSubstitutions_2(self):
     r1 = Routine(rules=[
         Substitution([["a"]], [["b"]]),
         Substitution([["b"]], [["c"]]),
         Substitution([["d"]], [["e"]]),
         Substitution([["y"]], [["z"]]),
     ])
     Optimizer(FontFeatures()).optimize_routine(r1, level=1)
     self.assertEqual(r1.asFea(), "    sub [a b d y] by [c c e z];\n")
    def test_complex(self):
        pos1 = Substitution(["a"], ["b"])
        pos2 = Substitution(["b"], ["c"])
        r1 = Routine(rules=[pos1], name="dummy1")
        r2 = Routine(rules=[pos2], name="dummy2")
        rr1 = RoutineReference(routine=r1)
        rr2 = RoutineReference(routine=r2)

        c = Chaining([["a"], ["b"]], lookups=[[rr1, rr2], None])
        self.assertEqual(c.asFea(), "sub a' lookup dummy1 lookup dummy2 b';")
Example #7
0
def test_routine_partition_not_needed():
    f = FontFeatures()

    s1 = Substitution([["A"]], [["A.grk"]], languages=["grek/*"])
    s2 = Substitution([["A"]], [["A.esp"]], languages=["grek/*"])
    r = Routine(rules=[s1, s2], flags=0x2)

    f.routines.append(r)
    f.partitionRoutine(r, lambda rule: tuple(rule.languages or []))

    assert len(f.routines) == 1

    r.rules = []
    f.partitionRoutine(r, lambda rule: tuple(rule.languages or []))
    assert len(f.routines) == 1
Example #8
0
def test_script_language_split():
    f = FontFeatures()

    s1 = Substitution([["question"]], [["questiongreek"]],
                      languages=[("grek", "*")])
    s2 = Substitution([["A"]], [["alpha"]], languages=[("grek", "ELL ")])
    s3 = Substitution([["question"]], [["questiondown"]],
                      languages=[("latn", "ESP ")])
    s4 = Substitution([["question"]], [["B"]], languages=[("latn", "POL ")])
    s5 = Substitution([["X"]], [["Y"]])
    r = Routine(rules=[s1, s2, s3, s4, s5])

    f.addFeature("locl", [r])
    f.buildBinaryFeatures(font)
    gsub = "\n".join(getXML(font["GSUB"].toXML))
    assert gsub == """<Version value="0x00010000"/>
Example #9
0
 def merge_two(self, first, second):
     assert len(first.input) == 1 and len(second.input) == 1
     assert len(first.replacement) == 1 and len(second.replacement) == 1
     assert first.precontext == second.precontext
     assert first.postcontext == second.postcontext
     firstmapping = {
         l: r
         for l, r in zip(first.input[0], first.replacement[0])
     }
     secondmapping = {
         l: r
         for l, r in zip(second.input[0], second.replacement[0])
     }
     for l, r in firstmapping.items():
         if r in secondmapping:
             firstmapping[l] = secondmapping[r]
     for l, r in secondmapping.items():
         if not (l in firstmapping):
             firstmapping[l] = r
     logger = logging.getLogger("fontFeatures")
     logger.info("Merging two adjacent single subs")
     if logger.isEnabledFor(logging.DEBUG):
         logger.debug(first.asFea())
         logger.debug(second.asFea())
     address = first.address or second.address
     return Substitution(
         [list(firstmapping.keys())],
         [list(firstmapping.values())],
         address=address,
         precontext=first.precontext,
         postcontext=first.postcontext,
     )
Example #10
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"
def test_multiple_languages_routine():
    f = FontFeatures()
    s1 = Substitution([["a"]], ["b"])
    expected = """languagesystem arab URD;
languagesystem arab FAR;

lookup Routine_1 {
    lookupflag 0;
    ;
    sub a by b;
} Routine_1;

feature locl {
    script arab;
    language URD;
            lookup Routine_1;

} locl;

feature locl {
    script arab;
    language FAR;
            lookup Routine_1;

} locl;
"""
    f = FontFeatures()
    r1 = Routine(rules=[s1], languages=[("arab", "URD "), ("arab", "FAR ")])
    f.addFeature("locl", [r1])
    assert f.asFea(do_gdef=False) == expected
Example #12
0
    def test_simple_sub(self):
        pos = Substitution(["a"], ["b"])
        r = Routine(rules=[pos], name="dummy")
        rr = RoutineReference(routine=r)

        c = Chaining([["a"], ["b"]], lookups=[[rr], None])
        self.assertEqual(c.asFea(), "sub a' lookup dummy b';")
 def test_GlyphClasses(self):
     r1 = Routine(rules=[
         Substitution([["a", "b", "c", "d", "e", "f", "g", "h"]], [["z"]]),
     ])
     ff = FontFeatures()
     Optimizer(ff).optimize_routine(r1, level=1)
     self.assertEqual(r1.asFea(), "    sub @class1 by z;\n")
     self.assertEqual(ff.namedClasses["class1"],
                      ("a", "b", "c", "d", "e", "f", "g", "h"))
Example #14
0
def test_routine_partition():
    f = FontFeatures()

    s1 = Substitution([["A"]], [["A.grk"]], languages=["grek/*"])
    s2 = Substitution([["A"]], [["A.esp"]], languages=["latn/ESP "])
    r = Routine(rules=[s1, s2], flags=0x2)

    f.routines.append(r)

    dummy = Routine(rules=[Substitution([["G"]], [["G"]])])
    f.routines.append(dummy)

    c = Chaining(
        [["A"], ["V"]],
        lookups=[
            [RoutineReference(routine=dummy),
             RoutineReference(routine=r)],
            [RoutineReference(routine=r),
             RoutineReference(routine=dummy)],
        ])
    r2 = Routine(rules=[c])
    f.routines.append(r2)

    f.addFeature("locl", [r])

    f.partitionRoutine(r, lambda rule: tuple(rule.languages or []))

    assert len(f.routines) == 4
    assert f.routines[0].flags == f.routines[1].flags
    assert len(f.routines[0].rules) == 1
    assert len(f.routines[1].rules) == 1
    assert f.routines[0].rules[0].replacement[0][0] == "A.grk"
    assert f.routines[1].rules[0].replacement[0][0] == "A.esp"

    assert len(c.lookups[0]) == 3
    assert len(f.features["locl"]) == 2
Example #15
0
 def _gsubLookup(self, lookup, prefix, suffix, ignore, chain, routine):
     sub = lookup.sub
     for key, val in sub.mapping.items():
         if not key or not val:
             path, line, column = sub.location
             log.warning(
                 f"{path}:{line}:{column}: Ignoring empty substitution")
             continue
         statement = None
         glyphs = self._coverage(key)
         replacements = self._coverage(val)
         if ignore:
             chain_context = (prefix, glyphs, suffix)
             statement = ast.IgnoreSubstStatement([chain_context])
         else:
             statement = Substitution(glyphs,
                                      replacements,
                                      precontext=prefix,
                                      postcontext=suffix,
                                      lookups=chain)
             if isinstance(
                     sub, VAst.SubstitutionReverseChainingSingleDefinition):
                 statement.reversed = True
         routine.rules.append(statement)
 def test_multiple(self):
     s = Substitution(["a"], ["b", "c"])
     self.assertEqual(s.asFea(), "sub a by b c;")
     self.assertEqual(s.involved_glyphs, set(["a", "b", "c"]))
     self.roundTrip(s)
Example #17
0
 def addSubRule(self):
     self.model().addRule(self.selectedIndexes()[0], Substitution([[]], [[]]))
     self.parent.editor.setWindowModified(True)
def test_language_ordering():
    f = FontFeatures()
    s1 = Substitution([["a"]], ["b"], languages=[("arab", "URD ")])
    s2 = Substitution([["a"]], ["c"], languages=[("arab", "FAR ")])
    s3 = Substitution([["x"], ["y"]], ["z"], languages=[("arab", "URD ")])

    f.addFeature("locl", [Routine(rules=[s1, s2, s3])])

    # When going to fea, we put everything in its own feature block to
    # avoid stupid problems with language systems
    expected = """languagesystem arab URD;
languagesystem arab FAR;

lookup Routine_1 {
    lookupflag 0;
    ;
    sub a by b;
} Routine_1;

lookup Routine_2 {
    lookupflag 0;
    ;
    sub a by c;
} Routine_2;

lookup Routine_3 {
    lookupflag 0;
    ;
    sub x y by z;
} Routine_3;

feature locl {
    script arab;
    language URD;
            lookup Routine_1;

} locl;

feature locl {
    script arab;
    language FAR;
            lookup Routine_2;

} locl;

feature locl {
    script arab;
    language URD;
            lookup Routine_3;

} locl;
"""
    assert f.asFea(do_gdef=False) == expected

    # But the same is true of multiple lookups in the same feature
    f = FontFeatures()
    r1 = Routine(rules=[s1])
    r2 = Routine(rules=[s2])
    r3 = Routine(rules=[s3])

    f.addFeature("locl", [r1, r2, r3])
    assert f.asFea(do_gdef=False) == expected
 def test_single_classes(self):
     s = Substitution([["a", "b"]], [["c", "d"]])
     self.assertEqual(s.asFea(), "sub [a b] by [c d];")
     self.assertEqual(s.involved_glyphs, set(["a", "b", "c", "d"]))
     self.roundTrip(s)
 def test_ligature(self):
     s = Substitution(["a", "b"], ["c"])
     self.assertEqual(s.asFea(), "sub a b by c;")
     self.assertEqual(s.involved_glyphs, set(["a", "b", "c"]))
     self.roundTrip(s)
 def test_ligature_expansion(self):
     s = Substitution([["f", "f.ss01"], ["i", "i.ss01"]], [["f_i", "f_i.ss01"]])
     self.assertEqual(s.asFea(), "    sub f i by f_i;\n    sub f.ss01 i.ss01 by f_i.ss01;\n")
     self.assertEqual(s.involved_glyphs, set(["f", "i", "f_i", "f.ss01", "i.ss01", "f_i.ss01"]))
     self.roundTrip(s)
 def test_multiple_expansion_middle(self):
     s = Substitution([["aa", "bb"]], ["d", ["aa", "bb"], "c"])
     self.assertEqual(s.asFea(), "    sub aa by d aa c;\n    sub bb by d bb c;\n")
     self.assertEqual(s.involved_glyphs, set(["aa", "bb", "c", "d"]))
     self.roundTrip(s)
 def test_alternate(self):
     s = Substitution(["a"], [["b", "c"]])
     self.assertEqual(s.asFea(), "sub a from [b c];")
     self.assertEqual(s.involved_glyphs, set(["a", "b", "c"]))
     self.roundTrip(s)
Example #24
0
    app = 0
    if QApplication.instance():
        app = QApplication.instance()
    else:
        app = QApplication(sys.argv)

    w = QWidget()
    w.resize(510, 210)
    v_box_1 = QVBoxLayout()

    proj = FluxProject("qalam.fluxml")
    proj.fontfeatures.features["mark"] = [proj.fontfeatures.routines[2]]
    proj.fontfeatures.features["curs"] = [proj.fontfeatures.routines[1]]

    # v = ValueRecord(yPlacement=0)
    # rule = Positioning(
    #     [["dda", "tda"]],
    #     [v],
    #     precontext=[["BEm2", "BEi3"]],
    #     postcontext=[["GAFm1", "GAFf1"]],
    # )
    rule = Substitution(input_=[["space"]], replacement=[["space"]])

    v_box_1.addWidget(QRuleEditor(proj, None))

    w.setLayout(v_box_1)

    w.show()
    sys.exit(app.exec_())
 def test_multiple_expansion(self):
     s = Substitution([["a", "b"]], [["a", "b"], "c"])
     self.assertEqual(s.asFea(), "    sub a by a c;\n    sub b by b c;\n")
     self.assertEqual(s.involved_glyphs, set(["a", "b", "c"]))
     self.roundTrip(s)