예제 #1
0
 def unparseMarkToMark(self, lookup):
     """Turn a GPOS6 (mark to mark) subtable into a fontFeatures Routine."""
     b = fontFeatures.Routine(name=self.getname("MarkToMark" + self.gensym()))
     self._fix_flags(b, lookup)
     for subtable in lookup.SubTable:  # fontTools.ttLib.tables.otTables.MarkBasePos
         assert subtable.Format == 1
         for classId in range(0, subtable.ClassCount):
             anchorClassPrefix = "Anchor" + self.gensym()
             marks = self._formatMarkArray(
                 subtable.Mark1Array, subtable.Mark1Coverage, classId
             )
             bases = self._formatMark2Array(
                 subtable.Mark2Array, subtable.Mark2Coverage, classId
             )
             b.addRule(
                 fontFeatures.Attachment(
                     anchorClassPrefix,
                     anchorClassPrefix + "_",
                     bases,
                     marks,
                     font=self.font,
                     address=self.currentLookup,
                     flags=lookup.LookupFlag,
                     force_markmark=True
                 )
             )
     return b, []
예제 #2
0
    def action(self, parser, aFrom, aTo, attachtype):
        bases = {}
        marks = {}

        def _category(k):
            return parser.fontfeatures.glyphclasses.get(
                k, parser.font[k].category)

        for k, v in parser.fontfeatures.anchors.items():
            if aFrom in v:
                bases[k] = v[aFrom]
            if aTo in v:
                marks[k] = v[aTo]
            if attachtype == "marks":
                bases = {
                    k: v
                    for k, v in bases.items() if _category(k) == "mark"
                }
            else:
                bases = {
                    k: v
                    for k, v in bases.items() if _category(k) == "base"
                }
            if attachtype != "cursive":
                marks = {
                    k: v
                    for k, v in marks.items() if _category(k) == "mark"
                }
        return [
            fontFeatures.Routine(rules=[
                fontFeatures.Attachment(
                    aFrom, aTo, bases, marks, font=parser.font)
            ])
        ]
예제 #3
0
 def unparseCursiveAttachment(self, lookup):
     """Turn a GPOS3 (cursive attachment) subtable into a fontFeatures Routine."""
     b = fontFeatures.Routine(name=self.getname("CursiveAttachment" + self.gensym()))
     self._fix_flags(b, lookup)
     entries = {}
     exits = {}
     for s in lookup.SubTable:
         assert s.Format == 1
         for glyph, record in zip(s.Coverage.glyphs, s.EntryExitRecord):
             if record.EntryAnchor:
                 entries[glyph] = (
                     record.EntryAnchor.XCoordinate,
                     record.EntryAnchor.YCoordinate,
                 )
             if record.ExitAnchor:
                 exits[glyph] = (
                     record.ExitAnchor.XCoordinate,
                     record.ExitAnchor.YCoordinate,
                 )
     b.addRule(
         fontFeatures.Attachment(
             "cursive_entry",
             "cursive_exit",
             entries,
             exits,
             flags=lookup.LookupFlag,
             address=self.currentLookup,
         )
     )
     return b, []
예제 #4
0
 def add_cursive_pos(self, location, glyphclass, entryAnchor, exitAnchor):
     self._start_routine_if_necessary(location)
     location = "%s:%i:%i" % (location)
     basedict, markdict = {}, {}
     if entryAnchor:
         basedict = {g: (entryAnchor.x, entryAnchor.y) for g in glyphclass}
     if exitAnchor:
         markdict = {g: (exitAnchor.x, exitAnchor.y) for g in glyphclass}
     s = fontFeatures.Attachment(base_name="cursive_entry",
                                 mark_name="cursive_exit",
                                 bases=basedict,
                                 marks=markdict,
                                 address=location,
                                 languages=self.currentLanguage)
     self.currentRoutine.addRule(s)
예제 #5
0
 def add_mark_base_pos(self, location, bases, marks):
     location = "%s:%i:%i" % (location)
     for baseanchor, markclass in marks:
         assert len(markclass.definitions) == 1
         markanchor = markclass.definitions[0].anchor
         s = fontFeatures.Attachment(
             base_name=markclass.name,
             mark_name=markclass.name,
             bases={g: (baseanchor.x, baseanchor.y)
                    for g in bases},
             marks={
                 g: (markanchor.x, markanchor.y)
                 for g in markclass.glyphs.keys()
             },
             address=location,
         )
     self.currentRoutine.addRule(s)
예제 #6
0
 def add_mark_base_pos(self, location, bases, marks):
     self._start_routine_if_necessary(location)
     location = "%s:%i:%i" % (location)
     for baseanchor, markclass in marks:
         assert len(markclass.definitions) == 1
         markanchor = markclass.definitions[0].anchor
         s = fontFeatures.Attachment(
             base_name=markclass.name,
             mark_name=markclass.name,
             bases={g: (baseanchor.x, baseanchor.y)
                    for g in bases},
             marks={
                 g: (markanchor.x, markanchor.y)
                 for g in markclass.glyphs.keys()
             },
             address=location,
             languages=self.currentLanguage)
         s.fontfeatures = self.ff
     self.currentRoutine.addRule(s)
예제 #7
0
    def action(self, args):
        (aFrom, aTo, attachtype) = args

        bases = {}
        marks = {}
        catcache = {}

        def _category(k):
            if k not in catcache:
                catcache[k] = self.parser.fontfeatures.glyphclasses.get(
                    k, self.parser.font[k].category)
            return catcache[k]

        for k, v in self.parser.fontfeatures.anchors.items():
            if aFrom in v:
                bases[k] = v[aFrom]
            if aTo in v:
                marks[k] = v[aTo]
            if attachtype == "marks":
                bases = {
                    k: v
                    for k, v in bases.items() if _category(k) == "mark"
                }
            else:
                bases = {
                    k: v
                    for k, v in bases.items() if _category(k) == "base"
                }
            if attachtype != "cursive":
                marks = {
                    k: v
                    for k, v in marks.items() if _category(k) == "mark"
                }
        return [
            fontFeatures.Routine(rules=[
                fontFeatures.Attachment(
                    aFrom, aTo, bases, marks, font=self.parser.font)
            ])
        ]
예제 #8
0
 def unparseMarkToBase(self, lookup):
     b = fontFeatures.Routine(name=self.getname("MarkToBase" +
                                                self.gensym()))
     self._fix_flags(b, lookup)
     for subtable in lookup.SubTable:  # fontTools.ttLib.tables.otTables.MarkBasePos
         assert subtable.Format == 1
         for classId in range(0, subtable.ClassCount):
             anchorClassPrefix = "Anchor" + self.gensym()
             marks = self.formatMarkArray(subtable.MarkArray,
                                          subtable.MarkCoverage, classId)
             bases = self.formatBaseArray(subtable.BaseArray,
                                          subtable.BaseCoverage, classId)
             b.addRule(
                 fontFeatures.Attachment(
                     anchorClassPrefix,
                     anchorClassPrefix + "_",
                     bases,
                     marks,
                     font=self.font,
                     address=self.currentLookup,
                     flags=lookup.LookupFlag,
                 ))
     return b, []
예제 #9
0
파일: Arabic.py 프로젝트: simoncozens/flux
    def accept(self):
        glyphnames = self.project.font.keys()
        isol_re = self.isol_re.text()
        init_re = self.init_re.text()
        medi_re = self.medi_re.text()
        fina_re = self.fina_re.text()

        init_class = []
        medi_class = []
        fina_class = []
        init_rules = fontFeatures.Routine(name="Init")
        medi_rules = fontFeatures.Routine(name="Medi")
        fina_rules = fontFeatures.Routine(name="Fina")
        # We know these are valid REs
        arabic_glyphs = [
            g for g in glyphnames if re.search(init_re, g)
            or re.search(medi_re, g) or re.search(fina_re, g)
        ]
        for g in glyphnames:
            m = re.search(isol_re, g)
            if not m:
                continue
            if m.groups():
                base_name = g.replace(m[1], "")
            else:
                base_name = g
            for g2 in arabic_glyphs:
                m = re.search(init_re, g2)
                if not m or not m.groups():
                    continue
                base_init = g2.replace(m[1], "")
                if base_init == base_name:
                    init_class.append(g2)
                    init_rules.addRule(fontFeatures.Substitution([[g]],
                                                                 [[g2]]))
                    break

            for g2 in arabic_glyphs:
                m = re.search(medi_re, g2)
                if not m or not m.groups():
                    continue
                base_medi = g2.replace(m[1], "")
                if base_medi == base_name:
                    medi_class.append(g2)
                    medi_rules.addRule(fontFeatures.Substitution([[g]],
                                                                 [[g2]]))
                    break

            for g2 in arabic_glyphs:
                m = re.search(fina_re, g2)
                if not m or not m.groups():
                    continue
                base_fina = g2.replace(m[1], "")
                if base_fina == base_name:
                    fina_class.append(g2)
                    fina_rules.addRule(fontFeatures.Substitution([[g]],
                                                                 [[g2]]))
                    break

        warnings = []
        if len(init_class) < 10 or len(init_class) > len(glyphnames) / 2:
            warnings.append(
                f"Init regexp '{init_re} matched a surprising number of glyphs ({len(init_class)})"
            )
        if len(medi_class) < 10 or len(medi_class) > len(glyphnames) / 2:
            warnings.append(
                f"Medi regexp '{medi_re} matched a surprising number of glyphs ({len(medi_class)})"
            )
        if len(fina_class) < 10 or len(fina_class) > len(glyphnames) / 2:
            warnings.append(
                f"Fina regexp '{fina_re} matched a surprising number of glyphs ({len(fina_class)})"
            )

        if len(warnings) and self.show_warnings(
                warnings) == QMessageBox.Cancel:
            return

        self.project.fontfeatures.routines.extend(
            [init_rules, medi_rules, fina_rules])
        self.project.fontfeatures.addFeature("init", [init_rules])
        self.project.fontfeatures.addFeature("medi", [medi_rules])
        self.project.fontfeatures.addFeature("fina", [fina_rules])
        if not "init" in self.project.glyphclasses:
            self.project.glyphclasses["init"] = {
                "type":
                "automatic",
                "predicates": [{
                    "type": "name",
                    "comparator": "matches",
                    "value": init_re
                }],
            }
        if not "medi" in self.project.glyphclasses:
            self.project.glyphclasses["medi"] = {
                "type":
                "automatic",
                "predicates": [{
                    "type": "name",
                    "comparator": "matches",
                    "value": medi_re
                }],
            }
        if not "fina" in self.project.glyphclasses:
            self.project.glyphclasses["fina"] = {
                "type":
                "automatic",
                "predicates": [{
                    "type": "name",
                    "comparator": "matches",
                    "value": fina_re
                }],
            }

        if self.doCursive.isChecked():
            exitdict = {}
            entrydict = {}
            for g in glyphnames:
                anchors = self.project.font[g].anchors
                if not anchors:
                    continue
                entry = [a for a in anchors if a.name == "entry"]
                exit = [a for a in anchors if a.name == "exit"]
                if len(entry):
                    entrydict[g] = (entry[0].x, entry[0].y)
                if len(exit):
                    exitdict[g] = (exit[0].x, exit[0].y)
            s = fontFeatures.Attachment(
                base_name="entry",
                mark_name="exit",
                bases=entrydict,
                marks=exitdict,
            )
            r = fontFeatures.Routine(name="CursiveAttachment", rules=[s])
            self.project.fontfeatures.routines.extend([r])
            self.project.fontfeatures.addFeature("curs", [r])

        return super().accept()