예제 #1
0
    def shapeText(self):
        features = []
        for k, box in self.features.items():
            if box.checkState() == Qt.PartiallyChecked:
                continue
            features.append({"tag": k, "value": box.isChecked()})

        buf = self.buildBuffer()

        self.messageTable.setRowCount(0)
        if not self.text:
            buf.clear_mask()
            self.qbr.set_buf(buf)
            self.fullBuffer = buf
            self.shaperOutput.setText(buf.serialize())
            return
        self.messageTable.clearSelection()
        self.lastBuffer = None
        self.skipped = []
        self.partialBuffers = {}
        shaper = Shaper(
            self.project.fontfeatures,
            self.project.font,
            message_function=self.addToTable,
        )
        self.prep_shaper(shaper, buf, features)
        shaper.execute(buf, features=features)

        self.qbr.set_buf(buf)
        self.fullBuffer = buf
        self.shaperOutput.setText(buf.serialize())
예제 #2
0
    def makeBuffer(self, before_after="before"):
        buf = VariationAwareBuffer(
            self.project.font,
            direction=self.buffer_direction,
        )
        if self.project.variations:
            buf.location = self.location
            buf.vf = self.project.variations
        buf.items = [
            VariationAwareBufferItem.new_glyph(g, self.project.font, buf)
            for g in self.representative_string
        ]
        shaper = Shaper(self.project.fontfeatures, self.project.font)

        shaper.execute(buf, features=self.makeShaperFeatureArray())
        routine = Routine(rules=[self.rule])
        # print("Before shaping: ", buf.serialize())
        if before_after == "after" and self.rule:
            print("Before application: ", buf.serialize())
            print(self.rule.asFea())
            buf.clear_mask()  # XXX
            try:
                routine.apply_to_buffer(buf)
            except Exception as e:
                print("Couldn't shape: " + str(e))
            print("After application: ", buf.serialize())
        return buf
예제 #3
0
def test_chain(parser):
    parser.parseString("""
Routine a_to_b { Substitute A -> B; };
Feature liga {
  Chain X ( A ^a_to_b) Y;
};
""")
    buf = Buffer(parser.font, unicodes="XAYXAX")
    shaper = Shaper(parser.fontfeatures, parser.font)
    shaper.execute(buf)
    assert buf.serialize(position=False) == "X|B|Y|X|A|X"
예제 #4
0
def test_swap2(parser):
    parser.parseString("""
LoadPlugin Swap;
Feature liga {
  Swap C ( A B ) E;
};
""")
    buf = Buffer(parser.font, unicodes="XABDCABDCABE")
    shaper = Shaper(parser.fontfeatures, parser.font)
    shaper.execute(buf)
    assert buf.serialize(position=False) == "X|A|B|D|C|A|B|D|C|B|A|E"
예제 #5
0
def test_swap(parser):
    parser.parseString("""
LoadPlugin Swap;
Feature liga {
  Swap A B;
};
""")
    buf = Buffer(parser.font, unicodes="CABD")
    shaper = Shaper(parser.fontfeatures, parser.font)
    shaper.execute(buf)
    assert buf.serialize(position=False) == "C|B|A|D"
예제 #6
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
예제 #7
0
    def makeRepresentativeString(self):
        inputglyphs = []
        if not self.rule:
            return inputglyphs
        # "x and x[0]" thing because slots may be empty if newly added
        if hasattr(self.rule, "precontext"):
            inputglyphs.extend([x and x[0] for x in self.rule.precontext])

        inputglyphs.extend([x and x[0] for x in self.rule.shaper_inputs()])

        if hasattr(self.rule, "postcontext"):
            inputglyphs.extend([x and x[0] for x in self.rule.postcontext])

        representative_string = [x for x in inputglyphs if x]
        for ix, g in enumerate(representative_string):
            if (g.startswith("@") and g[1:]
                    in self.project.fontfeatures.namedClasses.keys()):
                representative_string[
                    ix] = self.project.fontfeatures.namedClasses[g[1:]][0]

        # We use this representative string to guess information about
        # how the *real* shaping process will take place; buffer direction
        # and script, and hence choice of complex shaper, and hence from
        # that choice of features to be processed.
        unicodes = [
            self.project.font.codepointForGlyph(x)
            for x in representative_string
        ]
        unicodes = [x for x in unicodes if x]
        tounicodes = "".join(map(chr, unicodes))
        bufferForGuessing = Buffer(self.project.font, unicodes=tounicodes)
        self.buffer_direction = bufferForGuessing.direction
        self.buffer_script = bufferForGuessing.script
        # print("Guessed buffer direction ", self.buffer_direction)
        # print("Guessed buffer script ", self.buffer_script)
        shaper = Shaper(self.project.fontfeatures, self.project.font)
        bufferForGuessing = Buffer(self.project.font,
                                   glyphs=representative_string)
        shaper.execute(bufferForGuessing)
        self.availableFeatures = []
        for stage in shaper.stages:
            if not isinstance(stage, list):
                continue
            for f in stage:
                if (f not in self.availableFeatures
                        and f in self.project.fontfeatures.features):
                    self.availableFeatures.append(f)
        self.makeFeatureButtons()

        return representative_string
예제 #8
0
    def makeRepresentativeString(self):
        inputglyphs = []
        if not self.rule or not self.rule.bases or not self.rule.marks:
            return inputglyphs

        inputglyphs = [
            list(self.rule.bases.keys())[0],
            list(self.rule.marks.keys())[0]
        ]

        # We use this representative string to guess information about
        # how the *real* shaping process will take place; buffer direction
        # and script, and hence choice of complex shaper, and hence from
        # that choice of features to be processed.
        unicodes = [
            self.project.font.codepointForGlyph(x) for x in inputglyphs
        ]
        unicodes = [x for x in unicodes if x]
        tounicodes = "".join(map(chr, unicodes))
        bufferForGuessing = Buffer(self.project.font, unicodes=tounicodes)
        self.buffer_direction = bufferForGuessing.direction
        self.buffer_script = bufferForGuessing.script
        # print("Guessed buffer direction ", self.buffer_direction)
        # print("Guessed buffer script ", self.buffer_script)
        shaper = Shaper(self.project.fontfeatures, self.project.font)
        shaper.execute(bufferForGuessing)
        self.availableFeatures = []
        for stage in shaper.stages:
            if not isinstance(stage, list):
                continue
            for f in stage:
                if f not in self.availableFeatures and f in self.project.fontfeatures.features:
                    self.availableFeatures.append(f)
        self.makeFeatureButtons()

        return inputglyphs