File: Attachment.py

package info (click to toggle)
python-fontfeatures 1.9.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,096 kB
  • sloc: python: 9,112; makefile: 22
file content (101 lines) | stat: -rw-r--r-- 3,345 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Code for converting a Attachment object into feaLib statements
import fontTools.feaLib.ast as feaast
from fontFeatures.utils import categorize_glyph


def fix_scalar(scalar):
    if isinstance(scalar, int):
        return scalar
    if isinstance(scalar, float):
        return int(scalar)
    if hasattr(scalar, "axes"):
        # assume it's a variable scalar of some kind
        return scalar
    raise ValueError("Illegal anchor position %s" % scalar)


def _glyphref(g):
    if len(g) == 1:
        return feaast.GlyphName(g[0])
    return feaast.GlyphClass([feaast.GlyphName(x) for x in g])


def sortByAnchor(self):
    anchors = {}
    for name, pos in self.marks.items():
        if pos not in anchors:
            anchors[pos] = []
        anchors[pos].append(name)
    self.markslist = [(v, k) for k, v in anchors.items()]

    anchors = {}
    for name, pos in self.bases.items():
        if pos not in anchors:
            anchors[pos] = []
        anchors[pos].append(name)
    self.baseslist = [(v, k) for k, v in anchors.items()]


def feaPreamble(self, ff):
    if self.is_cursive:
        return []
    sortByAnchor(self)
    if "mark_classes_done" not in ff.scratch:
        ff.scratch["mark_classes_done"] = {}
    b = feaast.Block()
    for mark in self.markslist:
        if (self.fullname, tuple(mark[0])) not in ff.scratch["mark_classes_done"]:
            b.statements.append(
                feaast.MarkClassDefinition(
                    feaast.MarkClass(self.fullname),
                    feaast.Anchor(fix_scalar(mark[1][0]), fix_scalar(mark[1][1])),
                    _glyphref(mark[0]),
                )
            )
            ff.scratch["mark_classes_done"][(self.fullname, tuple(mark[0]))] = True
    return [b]


def asFeaAST(self):
    b = feaast.Block()
    if self.is_cursive:
        allglyphs = set(self.bases.keys()) | set(self.marks.keys())
        for g in allglyphs:
            b.statements.append(
                feaast.CursivePosStatement(
                    _glyphref([g]),
                    g in self.bases
                    and feaast.Anchor(
                        fix_scalar(self.bases[g][0]), fix_scalar(self.bases[g][1])
                    ),
                    g in self.marks
                    and feaast.Anchor(
                        fix_scalar(self.marks[g][0]), fix_scalar(self.marks[g][1])
                    ),
                )
            )
    else:
        if not hasattr(self, "baseslist"):
            sortByAnchor(self)  # e.g. when testing
        for base in self.baseslist:
            statementtype = feaast.MarkBasePosStatement
            if self.font:
                if categorize_glyph(self.font, base[0][0])[0] == "mark":
                    statementtype = feaast.MarkMarkPosStatement
            if self.force_markmark:
                statementtype = feaast.MarkMarkPosStatement
            b.statements.append(
                statementtype(
                    _glyphref(base[0]),
                    [
                        [
                            feaast.Anchor(
                                fix_scalar(base[1][0]), fix_scalar(base[1][1])
                            ),
                            feaast.MarkClass(self.fullname),
                        ]
                    ],
                )
            )

    return b